@fundar/data-chart-telling 1.18.0 → 1.20.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 (252) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +2 -1
  3. package/dist/configuration/config.svelte.js +1 -1
  4. package/dist/index.d.ts +4 -2
  5. package/dist/index.js +2 -1
  6. package/dist/layout/coordinates/CoordinatesLayout.svelte +3 -1
  7. package/dist/layout/facet/FacetLayout.svelte +54 -41
  8. package/dist/layout/geometry/GeometryLayout.svelte +57 -22
  9. package/dist/layout/geometry/ScaleFreeContext.d.ts +31 -0
  10. package/dist/layout/geometry/ScaleFreeContext.js +65 -0
  11. package/dist/layout/geometry/ScaleFreeMarks.svelte +14 -0
  12. package/dist/layout/geometry/ScaleFreeMarks.svelte.d.ts +7 -0
  13. package/dist/layout/geometry/ScaleGate.svelte.d.ts +8 -0
  14. package/dist/layout/geometry/ScaleGate.svelte.js +95 -0
  15. package/dist/layout/geometry/ScaleGateMarks.svelte +15 -0
  16. package/dist/layout/geometry/ScaleGateMarks.svelte.d.ts +7 -0
  17. package/dist/layout/hover/HoverShapes.d.ts +20 -8
  18. package/dist/layout/hover/HoverShapes.js +119 -59
  19. package/dist/layout/legend/ContinuousSection.svelte +10 -0
  20. package/dist/layout/legend/LegendState.svelte.d.ts +13 -1
  21. package/dist/layout/legend/LegendState.svelte.js +32 -0
  22. package/dist/layout/margins/Box.d.ts +4 -0
  23. package/dist/layout/margins/Box.js +14 -0
  24. package/dist/layout/margins/PlotMargins.svelte.js +26 -1
  25. package/dist/layout/plot/{Plot.svelte → AbstractPlot.svelte} +83 -6
  26. package/dist/layout/plot/{Plot.svelte.d.ts → AbstractPlot.svelte.d.ts} +4 -4
  27. package/dist/layout/plot/PublicPlotContext.d.ts +5 -0
  28. package/dist/layout/plot/PublicPlotContext.js +7 -0
  29. package/dist/layout/styles/ValueLabels.d.ts +109 -58
  30. package/dist/layout/styles/ValueLabels.js +299 -141
  31. package/dist/markers/MarkerKinds.d.ts +79 -1
  32. package/dist/markers/MarkerKinds.js +149 -23
  33. package/dist/markers/area/AreaMarker.svelte +1 -1
  34. package/dist/markers/band/BandMarker.svelte +2 -1
  35. package/dist/markers/bar/BarMarker.svelte +8 -6
  36. package/dist/markers/bollinger/BollingerMarker.svelte +1 -1
  37. package/dist/markers/box/BoxMarker.svelte +1 -1
  38. package/dist/markers/dot/DotRadius.d.ts +11 -0
  39. package/dist/markers/dot/DotRadius.js +21 -0
  40. package/dist/markers/geo/GeoHoverMarker.svelte +14 -11
  41. package/dist/markers/labels/CurveLabel.svelte +56 -0
  42. package/dist/markers/labels/CurveLabel.svelte.d.ts +9 -0
  43. package/dist/markers/labels/LabelMerge.d.ts +11 -0
  44. package/dist/markers/labels/LabelMerge.js +87 -0
  45. package/dist/markers/labels/MarkerLabel.svelte +36 -0
  46. package/dist/markers/labels/MarkerLabel.svelte.d.ts +10 -0
  47. package/dist/markers/labels/MarkerLabels.d.ts +52 -0
  48. package/dist/markers/labels/MarkerLabels.js +97 -0
  49. package/dist/markers/labels/geometry/BoxGeometry.d.ts +8 -0
  50. package/dist/markers/labels/geometry/BoxGeometry.js +101 -0
  51. package/dist/markers/labels/geometry/CurveGeometry.d.ts +34 -0
  52. package/dist/markers/labels/geometry/CurveGeometry.js +193 -0
  53. package/dist/markers/labels/geometry/PointGeometry.d.ts +9 -0
  54. package/dist/markers/labels/geometry/PointGeometry.js +22 -0
  55. package/dist/markers/labels/layouts/BoxLayout.d.ts +10 -0
  56. package/dist/markers/labels/layouts/BoxLayout.js +49 -0
  57. package/dist/markers/labels/layouts/PathLayout.d.ts +11 -0
  58. package/dist/markers/labels/layouts/PathLayout.js +91 -0
  59. package/dist/markers/labels/layouts/PointLayout.d.ts +19 -0
  60. package/dist/markers/labels/layouts/PointLayout.js +94 -0
  61. package/dist/markers/regression/RegressionMarker.svelte +1 -1
  62. package/dist/markers/text/Covering.d.ts +13 -0
  63. package/dist/markers/text/Covering.js +29 -0
  64. package/dist/markers/text/Declutter.d.ts +24 -3
  65. package/dist/markers/text/Declutter.js +46 -3
  66. package/dist/markers/text/TextMarker.svelte +90 -17
  67. package/dist/markers/text/TextMarker.svelte.d.ts +1 -1
  68. package/dist/markers/tick/TickMarker.svelte +1 -1
  69. package/dist/markers/utils/MarkerChannels.d.ts +1 -1
  70. package/dist/markers/utils/MarkerChannels.js +3 -2
  71. package/dist/markers/violin/ViolinMarker.svelte +1 -1
  72. package/dist/markers/waffle/WaffleMarker.svelte +1 -1
  73. package/dist/phases/context/RowContext.d.ts +2 -0
  74. package/dist/phases/context/RowContext.js +4 -2
  75. package/dist/phases/context/rowContextKey.d.ts +2 -0
  76. package/dist/phases/context/rowContextKey.js +2 -0
  77. package/dist/phases/markers/MarkerStyles.js +14 -11
  78. package/dist/phases/markers/MarkersPhase.d.ts +2 -3
  79. package/dist/phases/markers/MarkersPhase.js +17 -11
  80. package/dist/phases/sharedScales/SharedStepScales.d.ts +10 -0
  81. package/dist/phases/sharedScales/SharedStepScales.js +43 -0
  82. package/dist/phases/statistics/MarkerGrouping.js +5 -32
  83. package/dist/phases/statistics/MarkerInheritance.d.ts +11 -0
  84. package/dist/phases/statistics/MarkerInheritance.js +25 -0
  85. package/dist/phases/statistics/MarkerOrientation.d.ts +26 -0
  86. package/dist/phases/statistics/MarkerOrientation.js +29 -0
  87. package/dist/phases/statistics/StatisticsPhase.js +15 -15
  88. package/dist/phases/transforms/TransformsPhase.js +5 -3
  89. package/dist/plots/correlation/heatmap/Plot.svelte +2 -2
  90. package/dist/plots/correlation/heatmap/Plot.svelte.d.ts +0 -1
  91. package/dist/plots/correlation/heatmap/defaults.js +14 -1
  92. package/dist/plots/correlation/heatmap/markers.d.ts +0 -6
  93. package/dist/plots/correlation/heatmap/markers.js +5 -9
  94. package/dist/plots/correlation/scatter/Plot.svelte +2 -2
  95. package/dist/plots/correlation/scatter/Plot.svelte.d.ts +0 -1
  96. package/dist/plots/correlation/scatter/defaults.js +9 -3
  97. package/dist/plots/correlation/scatter/markers.d.ts +0 -9
  98. package/dist/plots/correlation/scatter/markers.js +21 -28
  99. package/dist/plots/distribution/box/BoxSummaries.d.ts +5 -0
  100. package/dist/plots/distribution/box/BoxSummaries.js +9 -0
  101. package/dist/plots/distribution/box/Plot.svelte +2 -2
  102. package/dist/plots/distribution/box/Plot.svelte.d.ts +0 -1
  103. package/dist/plots/distribution/box/defaults.js +11 -0
  104. package/dist/plots/distribution/box/markers.js +10 -1
  105. package/dist/plots/distribution/density/Plot.svelte +2 -2
  106. package/dist/plots/distribution/density/Plot.svelte.d.ts +0 -1
  107. package/dist/plots/distribution/density/defaults.js +16 -0
  108. package/dist/plots/distribution/density/markers.js +5 -1
  109. package/dist/plots/distribution/histogram/Plot.svelte +2 -2
  110. package/dist/plots/distribution/histogram/Plot.svelte.d.ts +0 -1
  111. package/dist/plots/distribution/histogram/defaults.js +16 -11
  112. package/dist/plots/distribution/histogram/markers.js +3 -3
  113. package/dist/plots/distribution/pyramid/Plot.svelte +2 -2
  114. package/dist/plots/distribution/pyramid/Plot.svelte.d.ts +0 -1
  115. package/dist/plots/distribution/pyramid/defaults.js +9 -2
  116. package/dist/plots/distribution/pyramid/markers.d.ts +0 -8
  117. package/dist/plots/distribution/pyramid/markers.js +6 -16
  118. package/dist/plots/distribution/violin/Plot.svelte +2 -2
  119. package/dist/plots/distribution/violin/Plot.svelte.d.ts +0 -1
  120. package/dist/plots/distribution/violin/defaults.js +11 -0
  121. package/dist/plots/distribution/violin/markers.js +27 -3
  122. package/dist/plots/evolution/area/Plot.svelte +2 -2
  123. package/dist/plots/evolution/area/Plot.svelte.d.ts +0 -1
  124. package/dist/plots/evolution/area/defaults.js +4 -7
  125. package/dist/plots/evolution/area/markers.js +3 -1
  126. package/dist/plots/evolution/line/Plot.svelte +2 -2
  127. package/dist/plots/evolution/line/Plot.svelte.d.ts +0 -1
  128. package/dist/plots/evolution/line/defaults.js +4 -6
  129. package/dist/plots/evolution/line/markers.js +3 -1
  130. package/dist/plots/evolution/slope/Plot.svelte +2 -2
  131. package/dist/plots/evolution/slope/Plot.svelte.d.ts +0 -1
  132. package/dist/plots/evolution/slope/defaults.js +4 -3
  133. package/dist/plots/evolution/slope/markers.d.ts +4 -3
  134. package/dist/plots/evolution/slope/markers.js +16 -9
  135. package/dist/plots/evolution/sparkline/Plot.svelte +2 -2
  136. package/dist/plots/evolution/sparkline/Plot.svelte.d.ts +0 -1
  137. package/dist/plots/evolution/sparkline/defaults.js +1 -1
  138. package/dist/plots/evolution/sparkline/markers.js +3 -1
  139. package/dist/plots/generic/Plot.svelte +42 -0
  140. package/dist/plots/generic/Plot.svelte.d.ts +25 -0
  141. package/dist/plots/generic/defaults.d.ts +4 -0
  142. package/dist/plots/generic/defaults.js +7 -0
  143. package/dist/plots/map/geo/Core.svelte +29 -6
  144. package/dist/plots/map/geo/Plot.svelte +40 -12
  145. package/dist/plots/map/geo/Plot.svelte.d.ts +0 -1
  146. package/dist/plots/map/geo/phases/data.d.ts +2 -1
  147. package/dist/plots/map/geo/phases/data.js +8 -2
  148. package/dist/plots/map/geo/phases/scales.js +6 -2
  149. package/dist/plots/map/geo/slices.d.ts +27 -3
  150. package/dist/plots/map/geo/slices.js +58 -5
  151. package/dist/plots/part-of-a-whole/treemap/Plot.svelte +2 -2
  152. package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +0 -1
  153. package/dist/plots/part-of-a-whole/treemap/defaults.js +2 -2
  154. package/dist/plots/ranking/bar/Plot.svelte +2 -2
  155. package/dist/plots/ranking/bar/Plot.svelte.d.ts +0 -1
  156. package/dist/plots/ranking/bar/defaults.js +13 -3
  157. package/dist/plots/ranking/bar/markers.js +12 -29
  158. package/dist/plots/ranking/bullet/Plot.svelte +2 -2
  159. package/dist/plots/ranking/bullet/Plot.svelte.d.ts +0 -1
  160. package/dist/plots/ranking/bullet/defaults.js +20 -0
  161. package/dist/plots/ranking/bullet/markers.js +7 -1
  162. package/dist/plots/ranking/cleveland/ClevelandMarkers.d.ts +2 -9
  163. package/dist/plots/ranking/cleveland/ClevelandMarkers.js +65 -47
  164. package/dist/plots/ranking/cleveland/Plot.svelte +2 -2
  165. package/dist/plots/ranking/cleveland/Plot.svelte.d.ts +0 -1
  166. package/dist/plots/ranking/cleveland/defaults.js +33 -2
  167. package/dist/plots/ranking/dumbbell/Plot.svelte +2 -2
  168. package/dist/plots/ranking/dumbbell/Plot.svelte.d.ts +0 -1
  169. package/dist/plots/ranking/forest/Plot.svelte +2 -2
  170. package/dist/plots/ranking/forest/Plot.svelte.d.ts +0 -1
  171. package/dist/plots/ranking/lollipop/Plot.svelte +2 -2
  172. package/dist/plots/ranking/lollipop/Plot.svelte.d.ts +0 -1
  173. package/dist/types/layout/context.d.ts +2 -0
  174. package/dist/types/layout/plot.d.ts +2 -0
  175. package/dist/types/layout/styles/bullet.d.ts +4 -1
  176. package/dist/types/layout/styles/geo.d.ts +3 -3
  177. package/dist/types/layout/styles/values.d.ts +51 -11
  178. package/dist/types/markers/axis/area.d.ts +5 -1
  179. package/dist/types/markers/axis/bar.d.ts +5 -2
  180. package/dist/types/markers/axis/bollinger.d.ts +2 -1
  181. package/dist/types/markers/axis/box.d.ts +2 -1
  182. package/dist/types/markers/axis/cell.d.ts +4 -1
  183. package/dist/types/markers/axis/line.d.ts +4 -1
  184. package/dist/types/markers/axis/rect.d.ts +4 -1
  185. package/dist/types/markers/axis/regression.d.ts +2 -1
  186. package/dist/types/markers/axis/tick.d.ts +2 -1
  187. package/dist/types/markers/axis/trail.d.ts +4 -1
  188. package/dist/types/markers/axis/violin.d.ts +2 -1
  189. package/dist/types/markers/axis/waffle.d.ts +5 -1
  190. package/dist/types/markers/basic/dot.d.ts +4 -1
  191. package/dist/types/markers/basic/text.d.ts +25 -21
  192. package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +5 -9
  193. package/dist/types/markers/channels/commonMarkerConfigWithOrientation.d.ts +5 -0
  194. package/dist/types/markers/channels/commonMarkerConfigWithOrientation.js +1 -0
  195. package/dist/types/markers/labels/box.d.ts +57 -0
  196. package/dist/types/markers/labels/box.js +1 -0
  197. package/dist/types/markers/labels/common.d.ts +15 -0
  198. package/dist/types/markers/labels/common.js +1 -0
  199. package/dist/types/markers/labels/path.d.ts +52 -0
  200. package/dist/types/markers/labels/path.js +1 -0
  201. package/dist/types/markers/labels/point.d.ts +40 -0
  202. package/dist/types/markers/labels/point.js +1 -0
  203. package/dist/types/markers/traits.d.ts +10 -0
  204. package/dist/types/phases/markers/phase.d.ts +1 -8
  205. package/dist/types/phases/statistics/phase.d.ts +8 -3
  206. package/dist/types/phases/styles/phase.d.ts +15 -3
  207. package/dist/types/phases/transforms/phase.d.ts +2 -0
  208. package/dist/types/plots/constants.d.ts +0 -12
  209. package/dist/types/plots/correlation/heatmap/props.d.ts +3 -2
  210. package/dist/types/plots/correlation/scatter/props.d.ts +3 -2
  211. package/dist/types/plots/data/geo.d.ts +19 -5
  212. package/dist/types/plots/distribution/box/props.d.ts +6 -2
  213. package/dist/types/plots/distribution/density/props.d.ts +2 -1
  214. package/dist/types/plots/distribution/histogram/props.d.ts +3 -2
  215. package/dist/types/plots/distribution/pyramid/props.d.ts +3 -2
  216. package/dist/types/plots/distribution/violin/props.d.ts +4 -1
  217. package/dist/types/plots/evolution/area/props.d.ts +3 -2
  218. package/dist/types/plots/evolution/line/props.d.ts +3 -2
  219. package/dist/types/plots/generic/props.d.ts +16 -0
  220. package/dist/types/plots/generic/props.js +1 -0
  221. package/dist/types/plots/generic/state.d.ts +4 -0
  222. package/dist/types/plots/generic/state.js +1 -0
  223. package/dist/types/plots/map/geo/props.d.ts +9 -3
  224. package/dist/types/plots/map/geo/state.d.ts +3 -1
  225. package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +4 -2
  226. package/dist/types/plots/ranking/bar/props.d.ts +3 -2
  227. package/dist/types/plots/ranking/cleveland/props.d.ts +3 -2
  228. package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -2
  229. package/dist/types/plots/ranking/forest/props.d.ts +5 -2
  230. package/dist/types/plots/ranking/lollipop/props.d.ts +3 -2
  231. package/dist/utils/ConfigEquality.d.ts +11 -0
  232. package/dist/utils/ConfigEquality.js +37 -0
  233. package/docs/architecture.md +9 -9
  234. package/docs/facets.md +12 -0
  235. package/docs/geo.md +35 -7
  236. package/docs/legend.md +6 -0
  237. package/docs/markers.md +2 -4
  238. package/docs/plots/ranking/bar.md +1 -1
  239. package/docs/plots/ranking/cleveland.md +1 -1
  240. package/docs/state.md +1 -1
  241. package/docs/styles-and-segments.md +1 -14
  242. package/docs/timeline.md +1 -1
  243. package/docs/transforms-and-statistics.md +1 -1
  244. package/docs/value-labels.md +159 -0
  245. package/examples/BarValues.svelte +1 -1
  246. package/llms-full.txt +5 -5
  247. package/llms.txt +1 -0
  248. package/package.json +3 -1
  249. package/dist/markers/utils/BoxLabel.d.ts +0 -58
  250. package/dist/markers/utils/BoxLabel.js +0 -175
  251. package/dist/markers/utils/MarkerLabel.svelte +0 -33
  252. package/dist/markers/utils/MarkerLabel.svelte.d.ts +0 -10
@@ -1,38 +1,28 @@
1
- import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
2
1
  import { SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
3
2
  import { ValueLabels } from '../../../layout/styles/ValueLabels';
4
3
  /**
5
- * ScatterPlot's `styles.values` as one `'text'` marker over the same
6
- * processed rows its dots draw, each labelled with its own `y` value. A label
7
- * sits beside its point and flips to the other side where its text would
8
- * cross the plot's edge (`edgeAware`).
4
+ * ScatterPlot's `styles.values` as labels of its dots: each labelled row with its own value, by default on a free
5
+ * spot around its point (`declutter: 'around'`) - a label with none is left out - or around its rim (`'path'`).
9
6
  */
10
- export function buildValueLabels(labels, state) {
11
- const { processedData } = state;
12
- if (!processedData?.data.length)
7
+ function buildValueLabels(labels, state, env) {
8
+ const rows = new Set(state.labelled ?? []);
9
+ if (rows.size === 0)
13
10
  return [];
14
- const { font, format } = labels;
15
- const position = ProcessedPositions.of(processedData);
16
11
  const nameOf = (d) => String(d[SERIES_KEY]);
17
- const valueOf = ValueLabels.valueOf(state);
12
+ const label = labels.label(env, (d) => labels.text(d), {
13
+ fill: 'currentColor',
14
+ seriesColor: (d) => state.colorForSeries?.(nameOf(d)),
15
+ fontSize: 11,
16
+ fontWeight: 500
17
+ });
18
+ if (labels.layout !== 'point')
19
+ return [label];
18
20
  return [
19
21
  {
20
- type: 'text',
21
- data: processedData.data,
22
- x: position.x,
23
- y: position.y,
24
- text: (d) => format(Number(valueOf(d)), d, nameOf(d)),
25
- styles: {
26
- ...font,
27
- fill: font?.fill ?? 'currentColor',
28
- fontSize: font?.fontSize ?? 11,
29
- fontWeight: font?.fontWeight ?? 500,
30
- dx: font?.dx ?? 8,
31
- dy: font?.dy ?? 0,
32
- textAnchor: labels.textAnchor ?? 'start',
33
- lineAnchor: font?.lineAnchor ?? 'middle'
34
- },
35
- edgeAware: true
22
+ ...label,
23
+ select: (row) => rows.has(row),
24
+ // A label on its own dot stays there; one beside it moves around it to a free spot.
25
+ declutter: labels.side === 'on' ? undefined : 'around'
36
26
  }
37
27
  ];
38
28
  }
@@ -126,5 +116,8 @@ export function buildMarks(state, env) {
126
116
  });
127
117
  }
128
118
  });
129
- return markers;
119
+ const labels = state.valueLabels?.show
120
+ ? buildValueLabels(state.valueLabels, state, env)
121
+ : undefined;
122
+ return ValueLabels.onMarkers(markers, 'dot', labels);
130
123
  }
@@ -1,6 +1,7 @@
1
1
  import type { HoverPosition, ProcessedRow } from '../../../types/phases';
2
2
  import type { BoxPlotState, BoxSummaryRow } from '../../../types/plots/distribution/box/state';
3
3
  import type { BoxSummary } from '../../../types/plots/distribution/box/props';
4
+ import type { PointGeometryOf } from '../../../types/markers/labels/point';
4
5
  /**
5
6
  * The boxes a box plot draws, one per series, category and facet panel - the same quartiles and whiskers
6
7
  * svelteplot's `BoxX`/`BoxY` compute, worked out once as each value's context ({@link context}), so its hover and
@@ -18,6 +19,10 @@ export declare class BoxSummaries {
18
19
  * Its own context is the box's, with the median for its value, and where it sits for `x` and `y`.
19
20
  */
20
21
  static of<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): BoxSummaryRow[];
22
+ /** Where each part of a box its value labels can write sits: beside the box, at the height of its value. */
23
+ static partPlacements<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): Record<string, Record<string, unknown>>;
24
+ /** Where a box's part label sits: at its category, level with the part's value, beside its band. */
25
+ static labelPoint<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): (value: symbol) => PointGeometryOf;
21
26
  /** Where a box's summary sits for hover: at its category, level with its median. */
22
27
  static position<TData extends Record<string, unknown>>(state: BoxPlotState<TData>): HoverPosition;
23
28
  /**
@@ -1,3 +1,4 @@
1
+ import { ValueLabels } from '../../../layout/styles/ValueLabels';
1
2
  import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
2
3
  import { quantile } from 'd3-array';
3
4
  import { SERIES_ID_KEY, SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
@@ -119,6 +120,14 @@ export class BoxSummaries {
119
120
  return summary;
120
121
  });
121
122
  }
123
+ /** Where each part of a box its value labels can write sits: beside the box, at the height of its value. */
124
+ static partPlacements(state) {
125
+ return ValueLabels.besideBand(state, ['min', 'p25', 'median', 'p75', 'max', 'outliers']);
126
+ }
127
+ /** Where a box's part label sits: at its category, level with the part's value, beside its band. */
128
+ static labelPoint(state) {
129
+ return ValueLabels.bandPoint(state, 'category');
130
+ }
122
131
  /** Where a box's summary sits for hover: at its category, level with its median. */
123
132
  static position(state) {
124
133
  const valueAxis = PlotAxes.valueOf(state);
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildBoxDefaults } from './defaults';
4
4
  import type { BoxPlotProps, BoxPlotCoreProps } from '../../../types/plots/distribution/box/props';
5
5
 
@@ -25,7 +25,7 @@
25
25
  }: BoxPlotProps<TData> = $props();
26
26
  </script>
27
27
 
28
- <Plot
28
+ <AbstractPlot
29
29
  core={core as BoxPlotCoreProps<TData>}
30
30
  defaults={buildBoxDefaults}
31
31
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { BoxPlotProps } from '../../../types/plots/distribution/box/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: BoxPlotProps<TData>;
@@ -29,6 +29,17 @@ export function buildBoxDefaults() {
29
29
  },
30
30
  // Each value's box: its quartiles and whiskers, worked out once for its tooltip and hover to read.
31
31
  context: (state) => BoxSummaries.context(state),
32
+ styles: {
33
+ values: {
34
+ layout: 'point',
35
+ // A quartile is worked out, not read: at most two decimals, as the tooltip writes it.
36
+ format: (value, number) => number(Math.round(value * 100) / 100),
37
+ parts: {
38
+ placements: BoxSummaries.partPlacements,
39
+ default: ['min', 'median', 'max']
40
+ }
41
+ }
42
+ },
32
43
  markers: { marks: buildMarks },
33
44
  hover: {
34
45
  // The hovered category's band behind its shape.
@@ -1,3 +1,5 @@
1
+ import { BoxSummaries } from './BoxSummaries';
2
+ import { SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
1
3
  /**
2
4
  * BoxPlot's "markers" phase: one `box` per visual segment of each series,
3
5
  * one box per category of its rows, filled with its series' color (or its
@@ -10,7 +12,7 @@
10
12
  export function buildMarks(state, env) {
11
13
  const { channels } = state.processedData;
12
14
  const { cfg } = env;
13
- return (state.processedGroups ?? []).flatMap((group) => {
15
+ const boxes = (state.processedGroups ?? []).flatMap((group) => {
14
16
  const name = group.series.name;
15
17
  const disabled = env.interaction?.fillFor(name);
16
18
  return group.visualSegments.map((seg) => {
@@ -38,4 +40,11 @@ export function buildMarks(state, env) {
38
40
  };
39
41
  });
40
42
  });
43
+ // The parts of each box `styles.values` labels: its whiskers' ends and its median by default, beside it.
44
+ const labels = state.valueLabels?.show
45
+ ? state.valueLabels.partMarkers(env, BoxSummaries.of(state), BoxSummaries.labelPoint(state), {
46
+ seriesColor: (row) => state.colorForSeries(String(row[SERIES_KEY]))
47
+ })
48
+ : [];
49
+ return [...boxes, ...labels];
41
50
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildDensityDefaults } from './defaults';
4
4
  import type {
5
5
  DensityPlotProps,
@@ -28,7 +28,7 @@
28
28
  }: DensityPlotProps<TData> = $props();
29
29
  </script>
30
30
 
31
- <Plot
31
+ <AbstractPlot
32
32
  core={core as DensityPlotCoreProps<TData>}
33
33
  defaults={buildDensityDefaults}
34
34
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { DensityPlotProps } from '../../../types/plots/distribution/density/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: DensityPlotProps<TData>;
@@ -1,3 +1,4 @@
1
+ import { PlotAxes } from '../../../phases/data/PlotAxes';
1
2
  import { buildMarks } from './markers';
2
3
  import { RowContext } from '../../../phases/context/RowContext';
3
4
  import { TooltipState } from '../../../layout/tooltip/TooltipState.svelte';
@@ -33,8 +34,23 @@ export function buildDensityDefaults() {
33
34
  }
34
35
  },
35
36
  transforms: {
37
+ // A curve is labelled at its peak.
38
+ labels: { select: 'max' },
36
39
  transforms: (state) => mergeDensity(state.transforms ?? [], state.axes?.isHorizontal ?? false)
37
40
  },
41
+ styles: {
42
+ values: {
43
+ layout: 'point',
44
+ layouts: { point: { side: 'above' }, path: { side: 'above', offset: 'max' } },
45
+ // The estimate tells a reader little: a label names the curve it is on, or a lone curve's peak position.
46
+ formatFor: (state) => {
47
+ const position = PlotAxes.other(PlotAxes.valueOf(state));
48
+ return (state.resolvedSeries?.length ?? 0) > 1
49
+ ? (value, number, { series }) => series ?? number(value)
50
+ : (_value, number, context) => number(Number(context[position]));
51
+ }
52
+ }
53
+ },
38
54
  scales: { zero: ['value'] },
39
55
  markers: { marks: buildMarks },
40
56
  hover: {
@@ -1,3 +1,4 @@
1
+ import { ValueLabels } from '../../../layout/styles/ValueLabels';
1
2
  import { Transforms } from '../../../phases/transforms/Transforms';
2
3
  /**
3
4
  * DensityPlot's "markers" phase: one `area` - or `line`, by `styles.mark` - per
@@ -10,7 +11,7 @@ export function buildMarks(state, env) {
10
11
  const { cfg } = env;
11
12
  const styles = state.styles;
12
13
  const asLine = styles?.mark === 'line';
13
- return (state.processedGroups ?? []).flatMap((group) => {
14
+ const marks = (state.processedGroups ?? []).flatMap((group) => {
14
15
  const name = group.series.name;
15
16
  const disabledFill = env.interaction?.fillFor(name);
16
17
  const disabledStroke = env.interaction?.strokeFor(name);
@@ -43,4 +44,7 @@ export function buildMarks(state, env) {
43
44
  }, transforms);
44
45
  });
45
46
  });
47
+ // `styles.values` labels each curve: its name at its peak by default, or along it.
48
+ const labels = state.valueLabels?.show ? state.valueLabels.forSeries(state, env) : undefined;
49
+ return ValueLabels.onMarkers(marks, asLine ? 'line' : 'area', labels);
46
50
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildHistogramDefaults } from './defaults';
4
4
  import type {
5
5
  HistogramPlotProps,
@@ -28,7 +28,7 @@
28
28
  }: HistogramPlotProps<TData> = $props();
29
29
  </script>
30
30
 
31
- <Plot
31
+ <AbstractPlot
32
32
  core={core as HistogramPlotCoreProps<TData>}
33
33
  defaults={buildHistogramDefaults}
34
34
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { HistogramPlotProps } from '../../../types/plots/distribution/histogram/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: HistogramPlotProps<TData>;
@@ -40,6 +40,7 @@ export function buildHistogramDefaults() {
40
40
  }
41
41
  },
42
42
  transforms: {
43
+ labels: {},
43
44
  transforms: (state, env) => mergeBin(state.transforms ?? [], env.cfg, state.axes?.isHorizontal ?? false)
44
45
  },
45
46
  // A bin's count and the edges it spans, for its label, its tooltip and its hover.
@@ -61,21 +62,25 @@ export function buildHistogramDefaults() {
61
62
  scales: { zero: ['value'] },
62
63
  styles: {
63
64
  values: {
65
+ layout: 'path',
66
+ // A bin's value runs up, or right on a horizontal histogram: its end is that edge.
67
+ layouts: (state) => {
68
+ const end = state.axes?.isHorizontal ? 'right' : 'top';
69
+ return {
70
+ path: { edge: end, side: 'outside' },
71
+ box: { anchor: 'middle' },
72
+ point: { anchor: end, side: state.axes?.isHorizontal ? 'after' : 'above' }
73
+ };
74
+ },
64
75
  // An `'outside'` label sits past its bin's end, which the longest bin takes to the edge.
65
76
  reach: (labels, state) => {
66
- if (labels.anchor !== 'outside')
77
+ const end = state.axes?.isHorizontal ? 'right' : 'top';
78
+ const { edge, side = 'outside' } = labels.placement;
79
+ if (labels.layout !== 'path' || edge !== end || side !== 'outside')
67
80
  return [];
68
81
  return state.axes?.isHorizontal
69
- ? [
70
- labels.edgeBox('0', { x: 'after', y: 'middle' }, { x: labels.offset('x') }, [
71
- 'right'
72
- ])
73
- ]
74
- : [
75
- labels.edgeBox('0', { x: 'middle', y: 'before' }, { y: -labels.offset('y') }, [
76
- 'top'
77
- ])
78
- ];
82
+ ? [labels.edgeBox('0', { x: 'after', y: 'middle' }, { x: labels.offset() }, ['right'])]
83
+ : [labels.edgeBox('0', { x: 'middle', y: 'before' }, { y: -labels.offset() }, ['top'])];
79
84
  }
80
85
  }
81
86
  },
@@ -1,5 +1,4 @@
1
1
  import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
2
- import { ValueLabels } from '../../../layout/styles/ValueLabels';
3
2
  import { Transforms } from '../../../phases/transforms/Transforms';
4
3
  import { resolveAccessor } from '../../../utils/accessors';
5
4
  import { PlotAxes } from '../../../phases/data/PlotAxes';
@@ -23,9 +22,10 @@ export function buildMarks(state, env) {
23
22
  const bottomOf = read(channels[`${value}1`]) ?? (() => 0);
24
23
  const countRead = read(channels[value]);
25
24
  const countOf = (d) => countRead ? Number(countRead(d)) : Number(position[value](d)) - Number(bottomOf(d));
26
- const labelFor = (name) => labels?.shapeLabel(env, (d) => (countOf(d) > 0 ? labels.format(countOf(d), d, name) : ''), {
25
+ const labelFor = (name) => labels?.label(env, (d) => (countOf(d) > 0 ? labels.text(d) : ''), {
27
26
  fill: 'currentColor',
28
- ...ValueLabels.boxAnchor(labels.anchor, { isHorizontal: value === 'x' })
27
+ labelled: state.labelled,
28
+ seriesColor: () => state.colorForSeries(name)
29
29
  });
30
30
  const rects = (state.processedGroups ?? []).flatMap((group) => {
31
31
  const disabled = env.interaction?.fillFor(group.series.name);
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildPyramidDefaults } from './defaults';
4
4
  import type {
5
5
  PyramidPlotProps,
@@ -27,7 +27,7 @@
27
27
  }: PyramidPlotProps<TData> = $props();
28
28
  </script>
29
29
 
30
- <Plot
30
+ <AbstractPlot
31
31
  core={core as PyramidPlotCoreProps<TData>}
32
32
  defaults={buildPyramidDefaults}
33
33
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { PyramidPlotProps } from '../../../types/plots/distribution/pyramid/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: PyramidPlotProps<TData>;
@@ -45,15 +45,22 @@ export function buildPyramidDefaults() {
45
45
  value: { tickFormat: (v) => String(Math.abs(Number(v))) }
46
46
  })
47
47
  },
48
+ transforms: { labels: {} },
48
49
  styles: {
49
50
  values: {
51
+ layout: 'path',
52
+ layouts: {
53
+ path: { edge: 'tip', side: 'outside' },
54
+ box: { anchor: 'middle' },
55
+ point: { anchor: 'top', side: 'above' }
56
+ },
50
57
  // A label past its bar's end reaches out on its own side, the longest bar's to the edge.
51
58
  reach: (labels, state) => {
52
- if (labels.anchor !== 'outside')
59
+ if (!labels.pastTip)
53
60
  return [];
54
61
  const axis = PlotAxes.valueOf(state);
55
62
  const isHorizontal = state.axes?.isHorizontal ?? true;
56
- const offset = labels.offset(axis);
63
+ const offset = labels.offset();
57
64
  return labels.extremes(state.resolvedSeries ?? [], axis).map(({ series, value }) => {
58
65
  const left = series.side === 'left';
59
66
  const text = labels.format(Math.abs(value), undefined, series.name);
@@ -1,11 +1,3 @@
1
1
  import type { PyramidPlotState, PyramidPlotEnv } from '../../../types/plots/distribution/pyramid/state';
2
2
  import type { AxisBasedMarkersConfig } from '../../../types/markers/common';
3
- /**
4
- * PyramidPlot's "markers" phase: one `role: 'segment'` bar per visual
5
- * segment, along the category axis the "data" phase read (horizontal bars for
6
- * categories on y, signed magnitude on x; vertical ones the other way) and with
7
- * no insets - prepended onto whatever the "statistics" phase already put in
8
- * `state.markers`. Emits no `role: 'hitArea'` markers - PyramidPlot's hover
9
- * matches nearest points rather than hit-testing category bands.
10
- */
11
3
  export declare function buildMarks<TData extends Record<string, unknown>>(state: PyramidPlotState<TData>, env: PyramidPlotEnv): AxisBasedMarkersConfig[];
@@ -1,4 +1,3 @@
1
- import { ValueLabels } from '../../../layout/styles/ValueLabels';
2
1
  import { resolveAccessor } from '../../../utils/accessors';
3
2
  import { seriesIdOf } from '../../../utils/grouping';
4
3
  import { PlotAxes } from '../../../phases/data/PlotAxes';
@@ -8,14 +7,6 @@ const GAP_KINDS = ['start', 'middle', 'end'];
8
7
  function signFor(s, magnitude) {
9
8
  return s.side === 'left' ? -magnitude : magnitude;
10
9
  }
11
- /**
12
- * PyramidPlot's "markers" phase: one `role: 'segment'` bar per visual
13
- * segment, along the category axis the "data" phase read (horizontal bars for
14
- * categories on y, signed magnitude on x; vertical ones the other way) and with
15
- * no insets - prepended onto whatever the "statistics" phase already put in
16
- * `state.markers`. Emits no `role: 'hitArea'` markers - PyramidPlot's hover
17
- * matches nearest points rather than hit-testing category bands.
18
- */
19
10
  export function buildMarks(state, env) {
20
11
  const { groupedSeries, gapFillMaps } = state;
21
12
  const gapDefaults = getConfiguration().pyramid.gap;
@@ -23,11 +14,6 @@ export function buildMarks(state, env) {
23
14
  const valueAxis = PlotAxes.valueOf(state);
24
15
  const isHorizontal = state.axes?.isHorizontal ?? true;
25
16
  const labels = state.valueLabels?.show ? state.valueLabels : undefined;
26
- /**
27
- * Where a series' labels sit on its bars, which run out from the shared baseline to its own side: left and right
28
- * of it on a horizontal pyramid, down and up on a vertical one.
29
- */
30
- const anchorOf = (side) => ValueLabels.boxAnchor(labels?.anchor ?? 'outside', { isHorizontal, negative: side === 'left' });
31
17
  /** One bar's own channels: its category, and its span from the baseline to its signed value. */
32
18
  const span = (category, to) => ({
33
19
  isHorizontal,
@@ -62,10 +48,14 @@ export function buildMarks(state, env) {
62
48
  data: realData,
63
49
  hover: 'style',
64
50
  ...span(processedCategory, signed),
65
- // Each bar writes its own magnitude, on its side of the baseline.
51
+ // Each bar writes its own magnitude; a bar's tip is on its own side of the baseline.
66
52
  ...(labels
67
53
  ? {
68
- label: labels.shapeLabel(env, (d) => labels.format(Math.abs(Number(getMagnitude(d))), d, group.series.name), { fill: 'currentColor', ...anchorOf(group.series.side) })
54
+ label: labels.label(env, (d) => labels.format(Math.abs(Number(getMagnitude(d))), d, group.series.name), {
55
+ fill: 'currentColor',
56
+ labelled: state.labelled,
57
+ seriesColor: () => state.colorForSeries(group.series.name)
58
+ })
69
59
  }
70
60
  : {}),
71
61
  styles: {
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildViolinDefaults } from './defaults';
4
4
  import type {
5
5
  ViolinPlotProps,
@@ -28,7 +28,7 @@
28
28
  }: ViolinPlotProps<TData> = $props();
29
29
  </script>
30
30
 
31
- <Plot
31
+ <AbstractPlot
32
32
  core={core as ViolinPlotCoreProps<TData>}
33
33
  defaults={buildViolinDefaults}
34
34
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { ViolinPlotProps } from '../../../types/plots/distribution/violin/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: ViolinPlotProps<TData>;
@@ -52,6 +52,17 @@ export function buildViolinDefaults() {
52
52
  },
53
53
  // Each value's box: its quartiles and whiskers, worked out once for its tooltip and hover to read.
54
54
  context: (state) => BoxSummaries.context(state),
55
+ styles: {
56
+ values: {
57
+ layout: 'point',
58
+ // A quartile is worked out, not read: at most two decimals, as the tooltip writes it.
59
+ format: (value, number) => number(Math.round(value * 100) / 100),
60
+ parts: {
61
+ placements: (state) => BoxSummaries.partPlacements(state),
62
+ default: ['median']
63
+ }
64
+ }
65
+ },
55
66
  markers: { marks: buildMarks },
56
67
  hover: {
57
68
  // The hovered category's band behind its shape.
@@ -1,3 +1,6 @@
1
+ import { ValueLabels } from '../../../layout/styles/ValueLabels';
2
+ import { BoxSummaries } from '../box/BoxSummaries';
3
+ import { SERIES_KEY } from '../../../phases/transforms/TransformsPhase';
1
4
  import { ProcessedPositions } from '../../../phases/transforms/ProcessedPositions';
2
5
  import { PlotAxes } from '../../../phases/data/PlotAxes';
3
6
  import { ViolinProfiles } from '../../../markers/violin/ViolinProfiles';
@@ -16,6 +19,16 @@ export function buildMarks(state, env) {
16
19
  const styles = state.styles;
17
20
  const { channels } = processed;
18
21
  const groups = state.processedGroups ?? [];
22
+ // Series share a band side by side only where they meet in it: one series per category - grouped by the category
23
+ // itself - fills each band.
24
+ const categoryOf = ProcessedPositions.of(processed, PlotAxes.valueOf(state))[PlotAxes.categoryOf(state)];
25
+ const seriesIn = new Map();
26
+ for (const row of processed.data) {
27
+ const key = String(categoryOf(row));
28
+ seriesIn.set(key, (seriesIn.get(key) ?? new Set()).add(row[SERIES_KEY]));
29
+ }
30
+ const shared = [...seriesIn.values()].some((series) => series.size > 1);
31
+ const slotOf = (index) => (shared ? { index, count: groups.length } : undefined);
19
32
  let peak;
20
33
  if (styles?.scale === 'shared') {
21
34
  const valueAxis = PlotAxes.valueOf(state);
@@ -43,7 +56,7 @@ export function buildMarks(state, env) {
43
56
  bandwidth: styles?.bandwidth,
44
57
  trim: styles?.trim,
45
58
  peak,
46
- slot: { index, count: groups.length },
59
+ slot: slotOf(index),
47
60
  styles: {
48
61
  // An outline asked for without a color is the fill's.
49
62
  ...(seg.styles.strokeWidth !== undefined
@@ -65,11 +78,22 @@ export function buildMarks(state, env) {
65
78
  x: channels.x,
66
79
  y: channels.y,
67
80
  thickness: boxWidth,
68
- slot: { index, count: groups.length },
81
+ slot: slotOf(index),
69
82
  bar: { fill: ink, fillOpacity: 1 },
70
83
  rule: { stroke: ink, strokeWidth: 1.5 },
71
84
  dot: { r: 0 },
72
85
  tickMinMax: false
73
86
  })));
74
- return [...violins, ...boxes];
87
+ // The parts of each violin's box `styles.values` labels: its median by default, beside it, in its series' slot.
88
+ const slots = new Map(groups.map((group, index) => [group.series.name, index]));
89
+ const summaries = state;
90
+ const labels = state.valueLabels?.show
91
+ ? state.valueLabels.partMarkers(env, BoxSummaries.of(summaries),
92
+ // Beside the narrow box inside each violin, the violin itself as wide as its values are dense.
93
+ ValueLabels.bandPoint(state, 'category', boxWidth ?? 0, (row) => {
94
+ const index = slots.get(String(row[SERIES_KEY]));
95
+ return index === undefined ? undefined : slotOf(index);
96
+ }), { seriesColor: (row) => state.colorForSeries(String(row[SERIES_KEY])) })
97
+ : [];
98
+ return [...violins, ...boxes, ...labels];
75
99
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildAreaDefaults } from './defaults';
4
4
  import type { AreaPlotProps, AreaPlotCoreProps } from '../../../types/plots/evolution/area/props';
5
5
 
@@ -25,7 +25,7 @@
25
25
  }: AreaPlotProps<TData> = $props();
26
26
  </script>
27
27
 
28
- <Plot
28
+ <AbstractPlot
29
29
  core={core as AreaPlotCoreProps<TData>}
30
30
  defaults={buildAreaDefaults}
31
31
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { AreaPlotProps } from '../../../types/plots/evolution/area/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: AreaPlotProps<TData>;
@@ -6,20 +6,17 @@ export function buildAreaDefaults() {
6
6
  data: {
7
7
  segments: { color: (style) => style?.fill, base: { flat: 'area' } }
8
8
  },
9
- statistics: { inheritPositions: true },
10
9
  scales: { zero: ['y'] },
11
10
  transforms: { labels: { select: 'last', skip: ValueLabels.skipGaps } },
12
11
  styles: {
13
12
  values: {
14
- anchor: 'start',
13
+ layout: 'point',
14
+ layouts: { point: { side: 'after' }, path: { edge: 'top', side: 'above', offset: 'end' } },
15
15
  format: (v, number, context) => `${context.series} - ${number(v)}`,
16
- reach: (labels, state) => labels.reachAtSeriesEnds(state)
16
+ reach: (labels, state) => (labels.layout === 'point' ? labels.reachAtSeriesEnds(state) : [])
17
17
  }
18
18
  },
19
- markers: {
20
- marks: buildMarks,
21
- valueLabels: (labels, state) => labels.atSeriesEnds(state)
22
- },
19
+ markers: { marks: buildMarks },
23
20
  timeline: { filterMode: 'upTo', interpolation: { value: 'y', key: ['grouping'] } }
24
21
  };
25
22
  }
@@ -1,3 +1,4 @@
1
+ import { ValueLabels } from '../../../layout/styles/ValueLabels';
1
2
  import { Transforms } from '../../../phases/transforms/Transforms';
2
3
  /**
3
4
  * AreaPlot's "markers" phase: one `area` per visual segment of each series,
@@ -44,5 +45,6 @@ export function buildMarks(state, env) {
44
45
  ...dimByName(group.series.name)
45
46
  }, transforms);
46
47
  }));
47
- return areas;
48
+ const labels = state.valueLabels?.show ? state.valueLabels.forSeries(state, env) : undefined;
49
+ return ValueLabels.onMarkers(areas, 'area', labels);
48
50
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" generics="TData extends Record<string, unknown>">
2
- import Plot from '../../../layout/plot/Plot.svelte';
2
+ import AbstractPlot from '../../../layout/plot/AbstractPlot.svelte';
3
3
  import { buildLineDefaults } from './defaults';
4
4
  import type { LinePlotProps, LinePlotCoreProps } from '../../../types/plots/evolution/line/props';
5
5
 
@@ -25,7 +25,7 @@
25
25
  }: LinePlotProps<TData> = $props();
26
26
  </script>
27
27
 
28
- <Plot
28
+ <AbstractPlot
29
29
  core={core as LinePlotCoreProps<TData>}
30
30
  defaults={buildLineDefaults}
31
31
  bind:margins
@@ -1,4 +1,3 @@
1
- import Plot from '../../../layout/plot/Plot.svelte';
2
1
  import type { LinePlotProps } from '../../../types/plots/evolution/line/props';
3
2
  declare function $$render<TData extends Record<string, unknown>>(): {
4
3
  props: LinePlotProps<TData>;