@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
@@ -0,0 +1,37 @@
1
+ /** Whether two configuration values hold the same, for a plot to tell a new configuration from one built again. */
2
+ export class ConfigEquality {
3
+ /** How many levels of objects and arrays it looks into; a value nested deeper only matches as the same object. */
4
+ static MAX_DEPTH = 6;
5
+ /**
6
+ * Whether `a` and `b` are the same value, or plain objects and arrays alike all the way down, dates of one
7
+ * time; anything else - a function, a class instance - only if it is the same object.
8
+ */
9
+ static same(a, b, depth = 0) {
10
+ if (Object.is(a, b))
11
+ return true;
12
+ if (depth >= ConfigEquality.MAX_DEPTH)
13
+ return false;
14
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
15
+ return false;
16
+ if (a instanceof Date || b instanceof Date) {
17
+ return a instanceof Date && b instanceof Date && +a === +b;
18
+ }
19
+ if (Array.isArray(a) || Array.isArray(b)) {
20
+ return (Array.isArray(a) &&
21
+ Array.isArray(b) &&
22
+ a.length === b.length &&
23
+ a.every((value, i) => ConfigEquality.same(value, b[i], depth + 1)));
24
+ }
25
+ if (!ConfigEquality.#isPlain(a) || !ConfigEquality.#isPlain(b))
26
+ return false;
27
+ const keys = Reflect.ownKeys(a);
28
+ if (keys.length !== Reflect.ownKeys(b).length)
29
+ return false;
30
+ return keys.every((key) => Object.prototype.hasOwnProperty.call(b, key) &&
31
+ ConfigEquality.same(a[key], b[key], depth + 1));
32
+ }
33
+ static #isPlain(value) {
34
+ const proto = Object.getPrototypeOf(value);
35
+ return proto === Object.prototype || proto === null;
36
+ }
37
+ }
@@ -23,7 +23,7 @@ Solid arrows are "renders"; the dotted line is "builds".
23
23
  flowchart TD
24
24
  Kind["<b>Plot.svelte</b><br/>BarPlot, LinePlot, ..."]
25
25
  Defaults["<b>defaults.ts</b><br/>phase options, markers, hover, timeline"]
26
- Plot["<b>Plot</b><br/>builds the Pipeline, one core per slice"]
26
+ AbstractPlot["<b>AbstractPlot</b><br/>builds the Pipeline, one core per slice"]
27
27
  Figure["<b>Figure</b><br/>box or grid cell, hover store, legend toggles"]
28
28
  Chrome["<b>FigureChrome</b><br/>title, legend, caption"]
29
29
  Timeline["<b>TimelineLayout</b>"]
@@ -32,9 +32,9 @@ flowchart TD
32
32
  Core["<b>Core</b><br/>its panel phases, or every phase"]
33
33
  Base["<b>BasePlotLayout</b><br/>svelteplot Plot, axes, markers"]
34
34
 
35
- Kind -->|core props + defaults| Plot
35
+ Kind -->|core props + defaults| AbstractPlot
36
36
  Kind -.- Defaults
37
- Plot --> Figure
37
+ AbstractPlot --> Figure
38
38
  Figure -->|with chrome| Chrome
39
39
  Figure -->|with a timeline| Timeline
40
40
  Figure -->|without one| Facet
@@ -44,12 +44,12 @@ flowchart TD
44
44
  Core --> Base
45
45
 
46
46
  classDef public stroke-width:3px
47
- class Kind,Plot public
47
+ class Kind,AbstractPlot public
48
48
  linkStyle default stroke:#8a8f98,stroke-width:2px
49
49
  ```
50
50
 
51
- 1. A kind's `Plot.svelte` splits its props into chrome (`title`, `legend`, ...), `timeline`, `facet` and the core props, and renders the shared `Plot` with its `defaults` builder.
52
- 2. `Plot` builds the kind's **`Pipeline`** once and renders a `Figure` whose body is the `TimelineLayout`, wrapping the `FacetLayout`, wrapping one `Core` per slice. Without a timeline or a facet, the one cell is the whole plot. Each facet's cell gets its scales (shared or free, per `facet.scales`) and whether its axes draw (per `facet.axes` and its edges in the grid).
51
+ 1. A kind's `Plot.svelte` splits its props into chrome (`title`, `legend`, ...), `timeline`, `facet` and the core props, and renders the shared `AbstractPlot` with its `defaults` builder.
52
+ 2. `AbstractPlot` builds the kind's **`Pipeline`** once and renders a `Figure` whose body is the `TimelineLayout`, wrapping the `FacetLayout`, wrapping one `Core` per slice. Without a timeline or a facet, the one cell is the whole plot. Each facet's cell gets its scales (shared or free, per `facet.scales`) and whether its axes draw (per `facet.axes` and its edges in the grid).
53
53
  3. `FacetLayout` turns the rows into facets - one per `by` value, flowed into `columns`, or one per `rows` x `cols` combination - and places them on a `Grid`, one `GridCell` each. Every plot reports the margins it settled on; once all have, each column and row pins its widest ones, so the plot areas line up.
54
54
  4. `Core` runs the pipeline over its props and hands the result to `BasePlotLayout`, which draws the svelteplot plot, the axes and the markers.
55
55
 
@@ -70,7 +70,7 @@ A `Pipeline` is an ordered list of **phase stages**, each a class in `phases/`.
70
70
  | `markers` | per panel | Composes the kind's marks, author markers and value labels |
71
71
  | `tooltip`, `hover` | per panel | Tooltip text, hover points and strategy |
72
72
 
73
- The first six are the **data phases** (`Pipeline.DATA_PHASES`). With a facet, `Plot` runs them once over every row (`PanelRun`, reused for a timeline step or a legend that omits a series), and each panel's `Core` runs only the rest. Without a facet, one `Core` runs every phase. Stages declared out of order still run in phase order, with a warning.
73
+ The first six are the **data phases** (`Pipeline.DATA_PHASES`). With a facet, `AbstractPlot` runs them once over every row (`PanelRun`, reused for a timeline step or a legend that omits a series), and each panel's `Core` runs only the rest. Without a facet, one `Core` runs every phase. Stages declared out of order still run in phase order, with a warning.
74
74
 
75
75
  ## Facets and the composer share one grid
76
76
 
@@ -115,7 +115,7 @@ Dependencies between layers go through Svelte context, so a layer never imports
115
115
  | Hover store | `Figure` (the outermost; nested figures share it) | every core's tooltip and hover sync |
116
116
  | Legend toggles | `Figure` (a figure with its own `legend` scopes them) | legends and every core below |
117
117
  | Timeline | `Figure` | the plot's timeline layout, the player bar, `useFigure().timeline` |
118
- | Shared timeline | `PlotComposer` with a `timeline` | `Plot`, which then draws no control of its own |
118
+ | Shared timeline | `PlotComposer` with a `timeline` | `AbstractPlot`, which then draws no control of its own |
119
119
  | Hover scope | `GridCell` in a composer's grid, and `HoverScope` around each facet | hover sync, to tell panels and facets apart |
120
120
  | Grid | `Grid` | `GridCell` (registers, gets its box and tag), `Figure` (takes a cell) |
121
121
  | Cell alignment | `GridCell` | `BasePlotLayout` (pinned margins), `MarginReporter` |
@@ -126,7 +126,7 @@ The public readers of that state are `useFigure()` and `usePlot()` ([Reading plo
126
126
 
127
127
  1. Define its props and state types under `types/plots/<kind>/`.
128
128
  2. Write `plots/<kind>/defaults.ts`: a builder returning the options of each phase it customises (`data`, `mapping`, `scales`, `styles`, `markers`, `hover`, `timeline`, ...).
129
- 3. Write `plots/<kind>/Plot.svelte`: split chrome, `timeline`, `facet` and core props and render the shared `Plot` with the builder.
129
+ 3. Write `plots/<kind>/Plot.svelte`: split chrome, `timeline`, `facet` and core props and render the shared `AbstractPlot` with the builder.
130
130
  4. Export it from `src/lib/index.ts`, add stories under `stories/plots/<kind>/`, tests under `tests/unit/plots/<kind>/`, and a page in `docs/plots/` with a row in the [Plots](plots.md) table.
131
131
 
132
132
  ## Conventions
package/docs/facets.md CHANGED
@@ -168,3 +168,15 @@ Panels line up: each plot reports the margins it settled on, and once all have,
168
168
  ## Maps
169
169
 
170
170
  `GeoPlot` takes `facet` and reads the field from each feature's `properties` (and from each marker row); features without the field are drawn in every panel.
171
+
172
+ The panels need not come from the features. `values` (or a grid's `rowValues` and `colValues`) name them, and they exist even when no feature carries the field: one layer of features serves every panel, with no copy of it per value. Each callback that reads a feature - `color`, `opacity`, `grouping`, `featureId`, `styles.onFeatureClick` - gets the slice it is drawn in as its last argument, `{ facet?: { value, row?, col? }, time? }`, and a tooltip's `format` finds the same `facet` and `time` in its context:
173
+
174
+ ```svelte
175
+ <GeoPlot
176
+ data={provinces}
177
+ facet={{ by: 'sex', values: ['Women', 'Men'] }}
178
+ color={(f, { facet }) => valueFor(f.properties.name, facet?.value)}
179
+ />
180
+ ```
181
+
182
+ The ramp spans every panel, each read in its own slice. See [Facets and timeline](geo.md#facets-and-timeline) on maps.
package/docs/geo.md CHANGED
@@ -19,13 +19,13 @@
19
19
 
20
20
  ## Data
21
21
 
22
- | Prop | Meaning |
23
- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
24
- | `data` | A GeoJSON `FeatureCollection`, an array of `Feature`s, or a TopoJSON `Topology` |
25
- | `object` | Required for a `Topology`: the key under `topology.objects` to draw. Needs the optional `topojson-client` package |
26
- | `featureId` | Accessor for each feature's stable id. Default: `feature.id ?? properties.id ?? properties.name`. It is the key of `segments`, and identifies features in hover and click |
27
- | `color` | `(feature) => number \| undefined` - the value of a choropleth. Features without one use `styles.fill` or their `segments` |
28
- | `excludeParts` | `(part, feature) => boolean`, where `part` is `{ centroid, geometry }` - drops geometry parts from drawing and hover (a distant territory drawn in an inset instead). `segments` still apply to what remains |
22
+ | Prop | Meaning |
23
+ | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
24
+ | `data` | A GeoJSON `FeatureCollection`, an array of `Feature`s, or a TopoJSON `Topology` |
25
+ | `object` | Required for a `Topology`: the key under `topology.objects` to draw. Needs the optional `topojson-client` package |
26
+ | `featureId` | Accessor for each feature's stable id. Default: `feature.id ?? properties.id ?? properties.name`. It is the key of `segments`, and identifies features in hover and click |
27
+ | `color` | `(feature, slice) => number \| undefined` - the value of a choropleth. Features without one use `styles.fill` or their `segments`. `slice` is the [facet panel and timeline step](#facets-and-timeline) it is drawn in |
28
+ | `excludeParts` | `(part, feature) => boolean`, where `part` is `{ centroid, geometry }` - drops geometry parts from drawing and hover (a distant territory drawn in an inset instead). `segments` still apply to what remains |
29
29
 
30
30
  ## Styles
31
31
 
@@ -146,6 +146,34 @@ An `inset` draws part of the map (or other data) in its own small panel, such as
146
146
 
147
147
  `location` is one of the 17 anchors (`'top-left'`, `'bottom-right'`, `'middle-left'`, ...); `features` filters by id from the plot's `data` (or give the inset its own `data`); `featurePartsFilter` narrows to geometry parts; `width` and `height` are fractions of the plot; an inset always fits its own content.
148
148
 
149
+ ## Facets and timeline
150
+
151
+ `facet` and `timeline` slice the map by a field each feature carries in its `properties` (and each marker's own rows by the same field); what lacks the field is drawn in every slice. To draw one layer of features in every panel, with no field on them, name the panels instead: `facet.values` for `by`, `rowValues` and `colValues` for `rows` and `cols`, or `timeline.values` for the steps. A slice's values are the ones named, in that order, then any more found in the features.
152
+
153
+ Every callback that reads a feature gets the slice it is drawn in as its last argument - `color`, `opacity`, `grouping`, `featureId` and `styles.onFeatureClick` - and a tooltip's `format` has it in its context:
154
+
155
+ | Field | Meaning |
156
+ | ------------- | ------------------------------------------------------------------ |
157
+ | `facet.value` | The panel: its `by` value, or a grid's `row · col` |
158
+ | `facet.row` | The panel's `rows` value, on a grid |
159
+ | `facet.col` | The panel's `cols` value, on a grid |
160
+ | `time` | The timeline step; the context is empty without `facet`/`timeline` |
161
+
162
+ ```svelte
163
+ <GeoPlot
164
+ data={provinces}
165
+ facet={{ by: 'sex', values: ['Women', 'Men'] }}
166
+ color={(f, { facet }) => valueFor(f.properties.name, facet?.value)}
167
+ tooltip={{
168
+ sync: true,
169
+ format: (f, number, { facet }) => `${f.properties.name} · ${facet?.value}`
170
+ }}
171
+ coordinates={{ projection: { type: 'mercator', domain: 'data' } }}
172
+ />
173
+ ```
174
+
175
+ The color ramp spans every panel and step, each read in its own slice, so colors compare across them; `facet.scales: 'free'` (or `timeline.scales`, with no facet) fits each slice's own instead, for panels that show different variables. To give each panel its own scheme too, return the panel from `grouping` and set `scales.color` in a `segments` entry per panel. With `projection.domain: 'data'`, each panel fits its own features. See also [Facets](facets.md#maps).
176
+
149
177
  ## Tooltip and hover
150
178
 
151
179
  `tooltip` works as on other plots with the hovered feature as the row (`format: (feature) => string`, or a `content` snippet). Add `{ type: 'geo-hover' }` for an in-map highlight. Hover matches the browser's own SVG hit-testing, so a feature is hovered where it is drawn.
package/docs/legend.md CHANGED
@@ -86,6 +86,12 @@ A continuous section narrows with `interactive: { enabled: true, mode: 'filter'
86
86
 
87
87
  Series can be toggled from code too: `useFigure().legend` has `off`, `isOff(name)`, `toggle`, `turnOff`, `turnOn` (see [Reading plot state](state.md)).
88
88
 
89
+ The range of a continuous section can be set from code as well: `useFigure().legend.setRange([min, max])` does what dragging the handles does - they move, and the plots filter or rescale to it, in the mode the section was set up with (a second argument, `'filter'` or `'rescale'`, overrides it). `setRange(null)`, or a span that covers the whole ramp, resets it; `legend.range` reads it back. A mini legend per panel can use it to apply its own panel's range to the figure's legend on a click.
90
+
91
+ ```svelte
92
+ <button onclick={() => figure.legend?.setRange([panelMin, panelMax])}>Use this range</button>
93
+ ```
94
+
89
95
  ## Adjusting the automatic legend
90
96
 
91
97
  An object adjusts the automatic legend while keeping what the plots read:
package/docs/markers.md CHANGED
@@ -174,16 +174,14 @@ A color or an opacity the function returns is drawn as it is, not mapped through
174
174
 
175
175
  ## A label in each shape
176
176
 
177
- A `rect`, `cell`, `bar` or `waffle` marker takes a `label`: a text written in the middle of each shape, with every option of a `text` marker but `type`, `data`, `x` and `y`, which the shape sets. It never takes the pointer from the shape under it, so `onclick` and the hover go on as they were.
177
+ A marker writes a label on each of its shapes with `label`: in each bar, cell, rect or waffle by default, beside the points of a line, an area or a dot, or along an edge or a line, with every option of a `text` marker besides. A list of labels writes each of them.
178
178
 
179
179
  ```ts
180
180
  { type: 'rect', data: tiles, x1: 'x1', x2: 'x2', y1: 'y1', y2: 'y2',
181
181
  label: { text: 'name', styles: { fill: 'white' }, fit: { fallback: 'value' } } }
182
182
  ```
183
183
 
184
- `anchor` puts the label against an edge (`'top'`, `'bottom'`, `'left'`, `'right'`) or in a corner (`'top-left'`...) instead of the middle, and `outside` puts one anchored to an edge beyond it; `gap` is its distance from the edge. A label outside is not fitted, and `fitMargins: true` grows the plot's margins to hold it where it would run past them. A label with a handler of its own (`onpointerenter`...) listens for the pointer; the others leave it to the shape. Its styles take functions of the row, to dim the label of a series, say. A label inside its shape with no `fill` of its own is written in the color that reads best on the shape's own - white on a dark one, near black on a light one - picked per row from the configuration's `text.label.contrast` (`['#ffffff', '#111827']`), or white or black where neither reaches the WCAG AA ratio of 4.5:1. The shape is read as it is seen: a `fillOpacity` under 1 blends it with the plot's `background`. One outside keeps its plot's color.
185
-
186
- The label is fitted to its shape unless `fit` is `false`. One too big is written smaller, down to `minFontSize`; at that size it breaks into the lines the shape holds and the last one is cut short with an ellipsis; when fewer than `minLetters` letters would show, `fallback` - a value, a field or a function of the row - is written instead; and when not even that fits, nothing is. `padding` is the room kept free inside each edge. The defaults of `gap`, `padding`, `minFontSize` (8) and `minLetters` (3) are the configuration's `text.label`: `setConfiguration({ text: { label: { gap: 6 } } })`. A `text` marker of your own takes the same `fit` with a box of its own (`x1`, `x2`, `y1`, `y2`), which is rarely what you want.
184
+ Its layouts and their options are those of a plot's value labels: see [Labels on markers](value-labels.md#labels-on-markers).
187
185
 
188
186
  ## Events
189
187
 
@@ -53,7 +53,7 @@ Bars where one axis holds the categories and the other the values. Categories on
53
53
  ![Horizontal grouped bars](../../images/horizontal-bars.png)
54
54
 
55
55
  - Several series sharing a category sit side by side, each in its slice of the category band. The gap between them is `bar.seriesPadding` in the configuration.
56
- - `transforms={[{ type: 'stackY' }]}` stacks the series instead. Stacking is always `stackY`, also for horizontal bars, because the value channel is the one stacked.
56
+ - `transforms={[{ type: 'stackY' }]}` stacks the series instead of putting them side by side. The stack runs along the value axis: `stackY` for vertical bars (values on `y`), `stackX` for horizontal ones (values on `x`, categories on `y`). The other one turns the category axis into a numeric one and the bars come out empty.
57
57
  - `scales.x.paddingInner` / `paddingOuter` set the spacing between category bands.
58
58
  - `styles.values.show` labels each bar; `styles.values.anchor` places the label (`'outside'`, `'middle'`, `'top'`, `'bottom'`, `'left'`, `'right'`, a corner such as `'top-left'`, or `'tip'` and `'base'`, the ends of the bar away from zero and on it).
59
59
  - The tooltip triggers anywhere over a bar's whole band, not just over the visible bar.
@@ -33,7 +33,7 @@ The general form of the family: per category, one dot for each series that has a
33
33
  - The connector spans the lowest and the highest dot of each category, so a series the legend omits leaves the range.
34
34
  - The value axis fits the values without reaching for zero; pin `scales.y.domain` to start it at zero.
35
35
  - Its defaults come from `cleveland` in the [configuration](../../theming.md): the connector is a neutral gray, 5 px thick.
36
- - `styles.values` writes each value: past the highest dot and the lowest of its category, and beside those between them. `select` (`'first'`, `'last'`, `'min'`, `'max'`, or a list) labels only those dots of each category, `series` only those series, and `color: 'series'` writes each label in its dot's series color. `format(value, number, context)` also gets the row in `context.row`, so a label can name its category (see [Styles and segments](../../styles-and-segments.md#value-labels)).
36
+ - `styles.values` writes each value: past the highest dot and the lowest of its category, and beside those between them. `select` (`'first'`, `'last'`, `'min'`, `'max'`, or a list) labels only those dots of each category, `series` only those series, and `color: 'series'` writes each label in its dot's series color. `format(value, number, context)` also gets the row in `context.row`, so a label can name its category (see [Value labels](../../value-labels.md)).
37
37
  - `segments` restyle the dots of chosen categories, as in [`DumbbellPlot`](dumbbell.md).
38
38
  - The tooltip reads one category at a time, listing every series.
39
39
 
package/docs/state.md CHANGED
@@ -7,7 +7,7 @@ A plot's state - its hover, legend, timeline, margins, scales, rows and size - c
7
7
  Works anywhere inside a figure, including the `header`, `footer` and `content` snippets of a plot or composer. It returns:
8
8
 
9
9
  - `hover` - `activeX`, `activeY`, `activeSeries`, `strategy`, `sync`, `source` (the id of the plot owning the hover).
10
- - `legend` (or `null`) - `entries`, `range`, `off` (names of hidden series), `isOff(name)`, `turnOff(name, action)`, `turnOn(name)`, `toggle(name, action)`. `action` is `{ mode: 'dim' | 'hide' | 'omit' | 'rescale' }`; `'omit'` removes the series and refits the axes, and `'rescale'` also makes the parts left of a whole (a stack, a treemap) the new 100%.
10
+ - `legend` (or `null`) - `entries`, `range`, `setRange([min, max] | null, mode?)` (narrows the continuous section as dragging it would, or resets it), `off` (names of hidden series), `isOff(name)`, `turnOff(name, action)`, `turnOn(name)`, `toggle(name, action)`. `action` is `{ mode: 'dim' | 'hide' | 'omit' | 'rescale' }`; `'omit'` removes the series and refits the axes, and `'rescale'` also makes the parts left of a whole (a stack, a treemap) the new 100%.
11
11
  - `timeline` (or `null`) - `enabled`, `steps`, `value`, `index`, `progress`, `playing`, `loop`, `speed`, `speeds`, `controls`, and `seek`, `seekIndex`, `seekValue`, `next`, `previous`, `play`, `pause`, `toggle`, `setLoop`, `setSpeed`, `cycleSpeed`. On a timeline of dates, `steps` and `value` are `Date`s and `seekValue` takes a `Date` or a date string.
12
12
 
13
13
  A footer that toggles series through the legend:
@@ -46,20 +46,7 @@
46
46
 
47
47
  ![End-of-line value labels](images/value-labels.png)
48
48
 
49
- | Field | Meaning |
50
- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51
- | `show` | Draws the labels. Off by default, except on a heatmap |
52
- | `anchor` | Where a label sits on its mark. On a line, area, slope or scatter plot: `'outside'`, `'start'`, `'middle'`, `'end'`, the side of its point the text is written on. On a bar, bullet, pyramid, histogram or heatmap - plots that label a shape - the label is in the shape: `'middle'`, an edge as the page draws it (`'top'`, `'bottom'`, `'left'`, `'right'`), a corner (`'top-left'`...), the end of the bar away from zero (`'tip'`) or the one on zero (`'base'`), whichever side of zero the value is; or beyond the tip, outside it: `'outside'` (the default). The labels are those of the shapes' own `label` - see [Markers](markers.md#a-label-in-each-shape) |
53
- | `select` | Which row of each group is labelled: `'first'`, `'last'`, `'min'`, `'max'`, or a list of them. A group is a series on a line or area plot (default `'last'`), a category on the plots that join dots (default: every dot) |
54
- | `series` | Labels only these series, by name |
55
- | `color` | `'series'` writes each label in its series' color; any other CSS color writes them all in it (`fontStyle.fill` wins) |
56
- | `decimals`, `prefix`, `suffix`, `signDisplay` | How the value reads, over `numbers.decimals` ([Number format](theming.md#number-format)); `format` replaces them |
57
- | `format` | `(value, number, context) => string`; `number` writes a value as the fields above ask, `context` is the labelled row's [context](state.md#row-context): its `series`, the `row` itself for its other fields, and what the plot works out |
58
- | `hoverIsolate` | Hovering a label dims every other series |
59
- | `fontStyle` | Text style: `fontSize`, `fill`, `dx`, `dy`, `textAnchor`, `lineAnchor`, `rotate`, `class`, ... Overrides the anchor's placement field by field |
60
- | `strokeStyle` | Style of the connector lines drawn from labels that had to move apart |
61
-
62
- Where the labels go depends on the plot: the end of each series on a line or area plot, one per bar on a bar, pyramid or histogram, one per point on a scatter, one per cell on a heatmap. On lines, overlapping labels spread apart, share one column and are joined to their points by elbow connectors; the right margin grows to fit them when it is `'auto'`. The spread is tuned by `text.declutter` in the [configuration](theming.md).
49
+ `styles.values` writes the plot's values on its own shapes: past the tip of each bar, beside the last point of each line, around each dot. Any of its options turns them on. `format` writes their text, `select` and `series` pick the rows labelled, and `layout` - `'point'`, `'path'` or `'box'` - changes where they go, with the options of each. See [Value labels](value-labels.md) for all of it.
63
50
 
64
51
  ### Frame
65
52
 
package/docs/timeline.md CHANGED
@@ -43,7 +43,7 @@
43
43
  | `values` | The steps, when not every distinct value of `accessor` - read like `accessor`'s values |
44
44
  | `filterMode` | `'exact'` shows the rows of the current step; `'upTo'` shows every row up to it (a cumulative reveal). `LinePlot` defaults to `'upTo'` |
45
45
  | `interpolate` | Tween values between steps so a scrub is smooth: `true`, or `{ key, value, create, progressEasing, segmentEasing }`. Line and bar plots default to interpolating their value channel |
46
- | `scales` | `'shared'` (default): axes span every step, so they hold still while scrubbing; `'free'` refits both to each step; `'free-x'` / `'free-y'` refit one and keep the other still |
46
+ | `scales` | `'shared'` (default): axes span every step (the widest any step reaches on its own rows), so they hold still while scrubbing; `'free'` refits both to each step; `'free-x'` / `'free-y'` refit one and keep the other still |
47
47
  | `onprogress`, `onvalue` | Called with the new position (`0`-`1`) and with the step it lands on - a `Date` on a timeline of dates, else the number |
48
48
  | `orientation`, `show`, `thickness` | A rule's direction (`'vertical'` default, beside the plot; `'horizontal'`), visibility and size |
49
49
 
@@ -72,7 +72,7 @@ Both derive rows from the data before drawing. A **transform** reshapes the rows
72
72
  | Filter | `filter` | Keep rows a test holds for |
73
73
  | Select | `select`, `selectFirst`, `selectLast`, `selectMinX`, `selectMaxX`, `selectMinY`, `selectMaxY` | Keep one row per group, such as each series' last point or peak |
74
74
 
75
- Bar stacking is always `stackY`, also for horizontal bars. A transform on a `HistogramPlot` is merged over the plot's default binning, so `{ type: 'binX', thresholds: 20 }` changes the bins and the rest stays.
75
+ A bar plot stacks along its value axis: `stackY` for vertical bars, `stackX` for horizontal ones. A transform on a `HistogramPlot` is merged over the plot's default binning, so `{ type: 'binX', thresholds: 20 }` changes the bins and the rest stays.
76
76
 
77
77
  ## Statistics
78
78
 
@@ -0,0 +1,159 @@
1
+ # Value labels
2
+
3
+ A plot can write its values on its own shapes: the value of each bar, the last value of each line, the count of each bin. They are the plot's `styles.values`. This page goes from turning them on to placing them precisely; the _Layout/Values_ stories in Storybook show every option drawn.
4
+
5
+ ## Turning them on
6
+
7
+ ```svelte
8
+ <BarPlot {data} x="province" y="value" styles={{ values: { show: true } }} />
9
+ ```
10
+
11
+ Setting any option of `styles.values` turns the labels on, so `show: true` is only needed alone: `styles={{ values: { decimals: 1 } }}` draws them too. `show: false` turns them off whatever else is set. A heatmap and a treemap show theirs by default.
12
+
13
+ Each plot kind places them its own way: past the tip of each bar, beside the last point of each line, on a free spot around each dot of a scatter, in the middle of each cell. The rest of this page is about changing that.
14
+
15
+ ## What a label says
16
+
17
+ A label writes the value it labels - its row context's `value` - as `decimals`, `prefix`, `suffix` and `signDisplay` ask, over the configuration's `numbers` (see [Number format](theming.md#number-format)):
18
+
19
+ ```ts
20
+ styles: { values: { decimals: 1, signDisplay: 'always', suffix: ' yrs' } }
21
+ ```
22
+
23
+ `format(value, number, context)` writes anything else. `number` writes a value as the fields above ask; `context` is what the plot knows of the labelled row (see [Row context](state.md#row-context)): its `series`, its `row` with the other fields of the data, and what the plot kind works out, such as a histogram bin's `count` or a treemap tile's `share`.
24
+
25
+ ```ts
26
+ format: (value, number, { series, row }) => `${row.country}: ${number(value)}`;
27
+ ```
28
+
29
+ ## Which values of a row
30
+
31
+ Most plots have one value per row. On a plot whose rows have several, each one is a **part** of the row's context, and `parts` picks the ones written:
32
+
33
+ | Plot | Parts | Default |
34
+ | --------- | ------------------------------------------------------------ | -------------------------- |
35
+ | Box | `'min'`, `'p25'`, `'median'`, `'p75'`, `'max'`, `'outliers'` | `['min', 'median', 'max']` |
36
+ | Violin | the same | `['median']` |
37
+ | Bullet | `'value'` (its bar), `'target'`, `'ranges'` (each bound) | `['value']` |
38
+ | Forest | `'value'` (its estimate), `'lower'`, `'upper'` | `['value']` |
39
+ | Any other | `'value'` | `['value']` |
40
+
41
+ Each part is written beside its shape at its own value: a box's beside the box, an interval's ends past each end. A part holding several values - a box's `'outliers'`, a bullet's `'ranges'` - writes a label for each. `parts` is a list, or a record turning each on (`true`) or giving it options of its own - where it sits, its `format`:
42
+
43
+ ```ts
44
+ styles: { values: { parts: ['median'] } }
45
+ styles: { values: { parts: { median: true, max: { format: (v) => `max ${v}` } }, series: 'virginica' } }
46
+ ```
47
+
48
+ Its type takes only the parts of the plot, and `format`'s `context.part` names the one written. A worked-out part - a quartile - is rounded to two decimals first.
49
+
50
+ ## Which rows
51
+
52
+ `select` picks the rows labelled of each group: `'first'`, `'last'`, `'min'`, `'max'`, or a list of them. A group is a series on a line or area plot (where the default is `'last'`) and a category on the plots that join dots; elsewhere every row is labelled. `series` labels only the series named.
53
+
54
+ ```ts
55
+ styles: { values: { select: ['min', 'max'], series: 'female' } }
56
+ ```
57
+
58
+ On a bar, a heatmap or a histogram, `select` applies to the `'point'` layout below, which labels some shapes and leaves the others bare.
59
+
60
+ ## Layouts
61
+
62
+ Where a label goes is its layout, one of three, named by the geometry it is laid out on:
63
+
64
+ | Layout | Where | Example |
65
+ | --------- | ------------------------------------------------------------------------------------ | -------------------------------------------------- |
66
+ | `'point'` | Beside a point of the shape: a line's last point, a dot, a corner of a bar | `{ layout: 'point', side: 'above' }` |
67
+ | `'path'` | Along an edge or a stroke of the shape: past a bar's tip, along a line, around a dot | `{ layout: 'path', edge: 'base', side: 'inside' }` |
68
+ | `'box'` | Inside the box of each shape, fitted to it: a bar, a cell, a tile | `{ layout: 'box', anchor: 'top' }` |
69
+
70
+ A plot kind takes the layouts its shapes can write, and its `styles.values` type takes only those: a line has no box to write in, so `LinePlot` takes `'point'` and `'path'`. Changing the layout is explicit, with `layout`; each kind brings its own defaults for every layout it takes, so `{ layout: 'path' }` alone is enough.
71
+
72
+ | Plot | Default | Also |
73
+ | ---------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------- |
74
+ | Line, slope, sparkline | `'point'` after the last point | `'path'`: each series' name along its line |
75
+ | Area | `'point'` after the last point | `'path'`: along the top (or bottom) edge of each area |
76
+ | Bar, bullet, pyramid | `'path'` past each bar's tip; `'box'` on a stacked bar | `'box'`, `'point'` |
77
+ | Histogram | `'path'` past each bin's top | `'box'`, `'point'` |
78
+ | Heatmap | `'box'` | `'path'`, `'point'` |
79
+ | Treemap | `'box'` | |
80
+ | Scatter, Cleveland, dumbbell, lollipop, forest | `'point'` beside each dot | `'path'`: around each dot's rim |
81
+ | Density | `'point'` over each curve's peak, naming it | `'path'`: each name along its curve, at its peak |
82
+ | Box, violin | `'point'` beside each box, at each part's value | |
83
+
84
+ ## Beside a point: `'point'`
85
+
86
+ The point depends on the shape: on a line or an area, a row's own point; on a dot, its center; on a bar or a cell, a point of its box, which `anchor` names - an edge's middle (`'top'`...) or a corner (`'top-left'`...).
87
+
88
+ From that point, `side` says where the text goes, as it reads: `'after'` it (to its right), `'before'` it, `'above'`, `'below'` or `'on'` it. `gap` is how far, 6px across and 8px up or down by default.
89
+
90
+ ```ts
91
+ styles: { values: { side: 'above', gap: 12 } } // a line's last value, over its point
92
+ styles: { values: { layout: 'point', anchor: 'top', select: 'max' } } // only the longest bar, over its top
93
+ ```
94
+
95
+ Labels that would overlap move apart:
96
+
97
+ - On a line, they fan out into lanes along one column, each joined back to its point by an elbow; `strokeStyle` styles those connectors. The margin on that side grows to hold them while it is `'auto'`.
98
+ - On a scatter, each takes a free spot around its dot - above it first (its own `side`), then on clockwise - clear of the other labels and dots, and one with no room is left out.
99
+ - A label on its own point (`side: 'on'`) stays there; where a shape drawn after its own covers it, it is left out. Of dots drawn over one another, only the top one's value shows.
100
+
101
+ ## Along a path: `'path'`
102
+
103
+ The path depends on the shape:
104
+
105
+ - On a bar or a cell, an edge of its box, which `edge` names: `'top'`, `'bottom'`, `'left'` or `'right'` as the page draws them, and on a bar `'tip'`, the end its value runs to, or `'base'`, the one at zero. The tip is read per row, so a bar below zero has its tip at its bottom, and a label past it goes under it.
106
+ - On a line, the line itself, curving with it: one label per series, its series' name unless `format` writes another.
107
+ - On an area, its top edge, or its bottom one with `edge: 'bottom'`; on a stack, each band's own.
108
+ - On a dot, its rim, over its top.
109
+
110
+ `side` is which side of the path the text sits on: on a shape `'outside'` (the default), `'inside'` or `'on'` its edge; on a line or an area `'above'` (the default), `'below'` or `'on'` it, where the text is drawn over a halo of the background. `offset` is where along the path, from its left or top end: `'start'`, `'middle'`, `'end'` or a percentage of its length; on a line or an area, `'max'` and `'min'` put each label at its own peak or trough. A label centred near an end of its line is moved in just enough to be written whole. `gap` is how far from it.
111
+
112
+ ```ts
113
+ styles: { values: { layout: 'path', edge: 'tip', side: 'inside' } } // inside each bar's end
114
+ styles: { values: { layout: 'path', side: 'on', offset: '60%' } } // each name on its line
115
+ ```
116
+
117
+ A label along a path is written whole, not fitted to its shape. Along a straight-segmented line or area, it follows a smooth curve through the same points, so its letters do not spread apart at the corners.
118
+
119
+ ## In a box: `'box'`
120
+
121
+ The label is written in the middle of its shape's box. `anchor` puts it against an edge (`'top'`, `'bottom'`, `'left'`, `'right'`) or in a corner (`'top-left'`...), `gap` from it.
122
+
123
+ A label in a box is fitted to it: one too wide is written smaller, down to `minFontSize`; at that size it breaks into the lines the box holds and the last one is cut short with an ellipsis; and when not even that fits, it is left out. `padding` is the room kept free inside each edge. The defaults of `gap`, `padding`, `minFontSize` (8) and `minLetters` (3) are the configuration's `text.label`: `setConfiguration({ text: { label: { gap: 6 } } })`.
124
+
125
+ ## How labels look
126
+
127
+ - A label inside its shape - in a box, or along an edge with `side: 'inside'` - with no color of its own is written in the color that reads best on the shape: white on a dark one, near black on a light one, picked per shape from the configuration's `text.label.contrast`. The shape is read as it is seen: a `fillOpacity` under 1 blends it with the plot's `background`.
128
+ - A label outside its shape is written in its series' color on a line or an area, and in the axis color elsewhere. `color: 'series'` writes each in its series' color, and any other CSS color writes them all in it.
129
+ - `fontStyle` sets the text's look - `fontSize`, `fontWeight`, `fill`, `rotate`, `class`... - but never where it sits, which is the layout's.
130
+ - `hoverIsolate: true` dims every other series while the pointer is over a label.
131
+
132
+ ## Labels on markers
133
+
134
+ A marker writes the same labels on its shapes with `label`, which takes a layout and its options like `styles.values`, with every option of a `text` marker besides (`text`, `styles`, `fit`, `declutter`...):
135
+
136
+ ```ts
137
+ { type: 'line', data, x: 'year', y: 'value', grouping: 'country',
138
+ label: { layout: 'path', text: 'country', offset: '80%' } }
139
+ ```
140
+
141
+ `text` is a field of the row, a function of it, or a literal. A list of labels writes each of them: `label: [{ text: 'value', anchor: 'top' }, { text: 'name', anchor: 'bottom' }]`. Each marker kind takes the layouts its shapes can write, `'box'` by default on shapes with a box and `'point'` on the others:
142
+
143
+ | Marker | `'box'` | `'path'` | `'point'` |
144
+ | --------------- | ------- | ----------------------------------- | ----------------------------- |
145
+ | `bar`, `waffle` | default | its edges, `'tip'` and `'base'` too | a point of its box (`anchor`) |
146
+ | `rect`, `cell` | default | its edges | a point of its box (`anchor`) |
147
+ | `line`, `trail` | | the line | default: each row's point |
148
+ | `area` | | its top or bottom edge | default: each row's top |
149
+ | `dot` | | its rim | default: its center |
150
+
151
+ On a marker:
152
+
153
+ - `select` picks a `'point'` label's rows of each `grouping` of the marker; it also takes a function of the row. Rows without a place (a gap) are never labelled.
154
+ - `declutter: true` (or `'lanes'`) fans overlapping point labels into lanes, `declutter: 'around'` moves each to a free spot around its point. The point labels of every marker of a plot are laid out together, so the ends of several lines fan out as one.
155
+ - A label takes the pointer only with a handler of its own (`onpointerenter`...); the others leave it to the shape under it, so `onclick` and the hover go on as they were. Its styles take functions of the row, to dim the label of a series, say.
156
+ - A box label's `fit` takes `false`, or an object: `minFontSize`, `minLetters`, `padding`, and `fallback` - a value, a field or a function of the row, written instead when fewer than `minLetters` letters would show.
157
+ - `fitMargins: true` grows the plot's margins to hold a label that runs past them.
158
+
159
+ A `text` marker of your own takes the same `declutter`, and `covers`: the shape each row's point sits in, so a label covered by a later row's shape is left out.
@@ -10,5 +10,5 @@
10
10
  data={REGION_VALUES.filter((row) => row.date === MONTHS.at(-1))}
11
11
  x="region"
12
12
  y="value"
13
- styles={{ values: { show: true, anchor: 'outside' } }}
13
+ styles={{ values: { show: true } }}
14
14
  />
package/llms-full.txt CHANGED
@@ -48,12 +48,12 @@ Two ways to give data, one per plot:
48
48
  | `facet` | `{ by: 'field', columns, gap, scales: 'shared'\|'free'\|'free-x'\|'free-y', mode: 'grid'\|'carousel'\|'paginated' }` or `{ rows, cols }`. |
49
49
  | `transforms` `statistics` | svelteplot transforms / derived summaries. `treemap` is the library's own transform: `{ type: 'treemap', value: 'count', levels: ['island', 'species'], tile: 'squarify', aspect: 1 }` makes a tile per distinct path of `levels` (outermost first), its area the sum of its rows' `value`, and gives a `rect` marker `x1`/`x2`/`y1`/`y2` in the unit square (`x`/`y` at each tile's centre for a `text`). `statistics` is `[{ type, ...options, series?, pooled? }]` (per series by default, `series: ['a']` only those, `pooled: true` all rows at once; a marker's own `.statistics` runs over its own `data`). Types: `regression` (`regressionType`: `'linear'|'quad'|'poly'|'exp'|'log'|'pow'|'loess'`, `order`, `base`, `span`, `confidence`, `styles`), `movingAverage` (`k`, `reduce`, `styles`), `bollinger` (`n`, `k`, `styles`), `density` (`kernel`, `bandwidth`, `styles`), `density2d` (`bandwidth`, `thresholds`, `styles`), `box` (the `box` marker's options), `deviation` (a rule at an estimator and a band around it, along the plot's value axis: `estimator`: `'mean'|'median'|'midrange'`, `spread`: `'stdev'|'mad'`, `k`, `rule` and `band`: styles or `false`, each with an optional `label: true | { text, styles: FontStyle }`, the band's also `edge: 'lower'|'upper'` and `position: 'inside'|'outside'`)|'upper'`). |
50
50
 
51
- Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `PyramidPlot` mirrors two series around zero; `HeatmapPlot` colors cells by `color`; `HistogramPlot` bins one numeric field; `DensityPlot` smooths one numeric field into a kernel density curve (`styles.mark: 'line'` draws a line instead of an area; a `densityX` transform sets `kernel` and `bandwidth`); `BoxPlot` x = category, y = value, one box per category (its tooltip row is the box summary: `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); `ViolinPlot` x = category, y = value (swap for horizontal), the mirrored density of each category's values with a box inside (`styles`: `kernel`, `bandwidth`, `trim`, `scale: 'width'|'shared'`, `box: false | width`; its tooltip row is a box plot's); `LollipopPlot` x = category, y = value, one dot on a stem per category (stems start at zero, or at the nearest end of a pinned domain; `styles.values` labels each dot); `DumbbellPlot` x = category, y = value, `color`/`grouping` names exactly two series, joined by a connector per category (another count warns); `ClevelandPlot` is the same for any number of series, joined from the lowest to the highest (use `grouping` for a numeric series field; `styles.values.select` (`'first'|'last'|'min'|'max'` or a list), `series` and `color: 'series'` choose and color the labelled dots; `styles.connector` sets the connector's `width` (number or `'dots'` for a band), `color` (one, `{ by: 'sign' | 'difference' | 'length' }` or a function), `opacity`, `arrow` (draws the from-to stretch as an arrow), `outside` (the part past the from/to dots), `label` (centered on the from-to stretch) and the `from`/`to` series of its difference); `ForestPlot` x = value, y = category (or swapped), one dot per row on a stem spanning its interval given by `lower`/`upper` fields or an `error` either side (the value axis fits the intervals; `styles.connector.caps` toggles the end ticks, on by default); `BulletPlot` is a bar plot with a `target` (field, function or number: a tick across the band) and `ranges` (upper bounds, each a field, function or number: bands from the baseline, the smallest darkest) drawn around its thin bars (the value axis reaches them); `SlopePlot` x = category (its first and last positions are the two moments), y = value, a line with a dot on every point per series, its first and last labelled before and after it by `styles.values` (the value axis is hidden by default; `scales.y.axisDisplay: 'visible'` shows it); `SparklinePlot` is a small `LinePlot` with no axes and no legend (`legend` and `margins` bring them back), a dot on each series' last point and its value beside it (`styles.values` formats it or turns it off with `show: false`; `facet` makes one per category); `TreemapPlot` takes `value` (a tile's area) and `grouping` (the whole path of a tile, fields joined by dots, outermost first: `'sector.branch'` - the last level names it, rows with one path are one tile, the outermost colors the tiles and the legend); a `treemap` entry in its `transforms` sets `tile` (`'squarify'` default, `'binary'`, `'slice'`, `'dice'`, `'sliceDice'`); its tiles are labelled by `styles.values` with their name over their share of the whole, cut short or reduced to the share alone where they do not fit; its `segments` can be keyed by the path of a tile (`'Tertiary.Finance'`) and `tooltip.format(row, number, context)` gets the tile's row and a `context` with its `series`, `name`, `path`, `value` and `share` (0-100); `ScatterPlot` takes `r` (size) and `symbol`; `GeoPlot` takes GeoJSON/TopoJSON in `data` and `coordinates` for the projection (`docs/geo.md`).
51
+ Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `PyramidPlot` mirrors two series around zero; `HeatmapPlot` colors cells by `color`; `HistogramPlot` bins one numeric field; `DensityPlot` smooths one numeric field into a kernel density curve (`styles.mark: 'line'` draws a line instead of an area; a `densityX` transform sets `kernel` and `bandwidth`); `BoxPlot` x = category, y = value, one box per category (its tooltip row is the box summary: `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`); `ViolinPlot` x = category, y = value (swap for horizontal), the mirrored density of each category's values with a box inside (`styles`: `kernel`, `bandwidth`, `trim`, `scale: 'width'|'shared'`, `box: false | width`; its tooltip row is a box plot's); `LollipopPlot` x = category, y = value, one dot on a stem per category (stems start at zero, or at the nearest end of a pinned domain; `styles.values` labels each dot); `DumbbellPlot` x = category, y = value, `color`/`grouping` names exactly two series, joined by a connector per category (another count warns); `ClevelandPlot` is the same for any number of series, joined from the lowest to the highest (use `grouping` for a numeric series field; `styles.values.select` (`'first'|'last'|'min'|'max'` or a list), `series` and `color: 'series'` choose and color the labelled dots; `styles.connector` sets the connector's `width` (number or `'dots'` for a band), `color` (one, `{ by: 'sign' | 'difference' | 'length' }` or a function), `opacity`, `arrow` (draws the from-to stretch as an arrow), `outside` (the part past the from/to dots), `label` (centered on the from-to stretch) and the `from`/`to` series of its difference); `ForestPlot` x = value, y = category (or swapped), one dot per row on a stem spanning its interval given by `lower`/`upper` fields or an `error` either side (the value axis fits the intervals; `styles.connector.caps` toggles the end ticks, on by default); `BulletPlot` is a bar plot with a `target` (field, function or number: a tick across the band) and `ranges` (upper bounds, each a field, function or number: bands from the baseline, the smallest darkest) drawn around its thin bars (the value axis reaches them); `SlopePlot` x = category (its first and last positions are the two moments), y = value, a line with a dot on every point per series, its first and last labelled before and after it by `styles.values` (the value axis is hidden by default; `scales.y.axisDisplay: 'visible'` shows it); `SparklinePlot` is a small `LinePlot` with no axes and no legend (`legend` and `margins` bring them back), a dot on each series' last point and its value beside it (`styles.values` formats it or turns it off with `show: false`; `facet` makes one per category); `TreemapPlot` takes `value` (a tile's area) and `grouping` (the whole path of a tile, fields joined by dots, outermost first: `'sector.branch'` - the last level names it, rows with one path are one tile, the outermost colors the tiles and the legend); a `treemap` entry in its `transforms` sets `tile` (`'squarify'` default, `'binary'`, `'slice'`, `'dice'`, `'sliceDice'`); its tiles are labelled by `styles.values` with their name over their share of the whole, cut short or reduced to the share alone where they do not fit; its `segments` can be keyed by the path of a tile (`'Tertiary.Finance'`) and `tooltip.format(row, number, context)` gets the tile's row and a `context` with its `series`, `name`, `path`, `value` and `share` (0-100); `ScatterPlot` takes `r` (size) and `symbol`; `GeoPlot` takes GeoJSON/TopoJSON in `data` and `coordinates` for the projection; its `facet.values` name the panels of one layer of features, and `color`, `opacity`, `grouping`, `featureId` and the tooltip `format` get the slice `{ facet?, time? }` (`docs/geo.md`).
52
52
 
53
53
  ## Switches
54
54
 
55
55
  - **Hover and tooltip** are enabled by `tooltip` and/or a hover marker. The usual look: `tooltip={true} markers={[{ type: 'hover' }]}`. `tooltip.strategy` is `'x' | 'y' | 'punctual' | 'series'`. The hover marker's `active` and `others` restyle the hovered shapes and the rest (`fill`, `fillOpacity`, `stroke`, `strokeWidth`, `strokeOpacity`, `strokeDasharray`, each a value or a function of the row): `markers={[{ type: 'hover', active: { fillOpacity: 1 }, others: { fillOpacity: 0.3 } }]}`. It works on a treemap's tiles, a bar plot's bars and a heatmap's cells as they are; a marker of yours takes it with `hover: true` (also a hit area) or `hover: 'style'`. A series the legend dims stays hoverable but keeps its dimmed fill; one it hides, omits or rescales is never hovered. The hover marker draws its plot kind's own hover - a crosshair along the strategy's axes with a dot and the value on line, area and density plots; a crosshair through the point and its value on a scatter plot; a rule along the value axis with a dot and the value on slope and Cleveland-family plots; the hovered category's `band` behind bar, bullet, box, violin and pyramid plots; the hovered bin's span behind a histogram; a dot on a sparkline; on a treemap or a heatmap, only the hovered tile or cell outlined (`hover.active` in the configuration) - following the strategy in force (a composer's can change while shown), laid out as `back` (markers behind the plot's shapes) and `front` (in front), lists of any markers but `hover` that replace the kind's when set (`back: []` draws nothing behind). They draw the hovered points (`x`, `y`, `label`, `series`, `color`, `areaInset`, `row`), and what they leave unset comes from the hover: `x`/`y`, a `rule`'s and a `band`'s `value`, a `text`'s `text`, the configuration's `hover` look and the series color. `points: 'active' | (point) => boolean` draws only the point under the pointer, or some: `{ type: 'hover', back: [{ type: 'rule', axis: 'x', points: 'active' }], front: [{ type: 'dot' }] }`.
56
- - **Value labels**: `styles={{ values: { show: true } }}`. On a LinePlot they sit at the end of each series, spread apart automatically, and the right margin grows to fit them (keep `margins.right` at `'auto'`). Format with `values.format: (value, number, context) => string` (`context.series`, `context.row`); style with `values.fontStyle`.
56
+ - **Value labels**: any option of `styles.values` turns them on (`{ show: true }` alone too). Each kind places them its own way: past each bar's tip, after a line's last point (overlapping ones fan out into lanes and the margin grows to fit them; keep `margins.right` at `'auto'`), around each scatter dot, in each heatmap cell. `layout` changes it, with the options of each: `'point'` (`side: 'after' | 'before' | 'above' | 'below' | 'on'`, `gap`; `anchor` on bars and cells), `'path'` (`edge`, with `'tip'`/`'base'` on bars; `side`; `offset: 'start' | 'middle' | 'end' | '40%'`; on a line it writes each series' name along it), `'box'` (`anchor`, fitted to the shape). A kind's `styles.values` type takes only its layouts. Text: `format: (value, number, context) => string` (`context.series`, `context.row`), or `decimals`/`prefix`/`suffix`/`signDisplay`; `select` and `series` pick the rows; `color: 'series'`; `fontStyle` styles the text but never places it. On a plot whose rows have several values, `parts` picks which: `BoxPlot`/`ViolinPlot` `'min' | 'p25' | 'median' | 'p75' | 'max' | 'outliers'` (box default `['min','median','max']`), `BulletPlot` `'value' | 'target' | 'ranges'`, `ForestPlot` `'value' | 'lower' | 'upper'`; a list, or a record with per-part options (`{ median: { format } }`); every value is read off the row context (`context.part` in `format`). `DensityPlot` names each curve at its peak. A marker's `label` takes the same layouts. See `docs/value-labels.md`.
57
57
  - **Toggling series from the legend**: `interactive.enabled` on the series section.
58
58
  - **A frame** around the plot area: `styles={{ frame: true }}`.
59
59
 
@@ -69,7 +69,7 @@ Per kind: `BarPlot` x = category, y = value (swap for horizontal bars); `Pyramid
69
69
  8. Narrow plots with long category or series names: shorten the text in the data, format with `tickFormat` / `values.format`, or give `margins` more room.
70
70
  9. In Svelte 5 components, `state` is taken by the `$state` rune: name local variables otherwise.
71
71
  10. In a `facet`, every panel draws the plot's `markers` and `segments`. Give one a `facet` (a `by` value, a list of them, or `{ row, col }` in a `rows`/`cols` grid) to draw it only in the panels it names: `markers={[{ type: 'rule', axis: 'y', value: 10, facet: 'GBA' }]}`, `segments={{ Services: [{ facet: 'Cuyo', styles: { stroke: { strokeDasharray: '4 4' } } }] }}`. A plot with no facet leaves out whatever names one.
72
- 10. Stacking is `transforms={[{ type: 'stackY' }]}`, also for horizontal bars (the value channel is the one stacked).
72
+ 10. Bars stack along their value axis: `transforms={[{ type: 'stackY' }]}` for vertical bars (values on `y`), `transforms={[{ type: 'stackX' }]}` for horizontal ones (values on `x`, categories on `y`); the wrong one draws no bars.
73
73
 
74
74
  ## Reading and driving plot state (custom UI)
75
75
 
@@ -78,7 +78,7 @@ Inside a plot's snippets (`header`, `footer`, tooltip `content`) or any child of
78
78
  - `useFigure()` returns `{ hover, legend, timeline }` for the whole figure.
79
79
  - `usePlot()` returns the same plus `margins`, `scales`, `axes`, `data`, `width`, `height`, `svelteplot` (inside a plot, e.g. a `component` marker), and `contextOf(row)`.
80
80
  - Row context: every row a plot draws has a context worked out once - `series`, `x`, `y`, `value`, `row` and what the kind adds (`TreemapPlot`: `name`, `path`, `share`; `HistogramPlot`: `count`, `from`, `to`; `BoxPlot`/`ViolinPlot`: `category`, `min`, `p25`, `median`, `p75`, `max`, `count`, `outliers`; `DensityPlot`'s `value` is the estimate). `tooltip.format`, `styles.values.format`, the `hover` marker's points (`point.context`) and `RowContext.of(row)` all read it.
81
- - `legend.off` (names of hidden series), `legend.isOff(name)`, `legend.toggle(name, action)`, `turnOff`, `turnOn`. `action` is `{ mode: 'dim' | 'hide' | 'omit' | 'rescale' }`; `'omit'` removes the series and refits the axes, and `'rescale'` also makes the parts left of a whole (a stack, a treemap) the new 100%, so the visible domain follows `legend.off`.
81
+ - `legend.off` (names of hidden series), `legend.setRange([min, max] | null)` (narrows a continuous section), `legend.isOff(name)`, `legend.toggle(name, action)`, `turnOff`, `turnOn`. `action` is `{ mode: 'dim' | 'hide' | 'omit' | 'rescale' }`; `'omit'` removes the series and refits the axes, and `'rescale'` also makes the parts left of a whole (a stack, a treemap) the new 100%, so the visible domain follows `legend.off`.
82
82
  - `timeline.steps`, `value`, `progress`, `playing`, `seek(p)`, `seekValue(v)`, `next()`, `previous()`, `play()`, `pause()`, `toggle()`, `setSpeed()`.
83
83
  - `hover.activeX`, `activeY`, `activeSeries`, `source`.
84
84
 
@@ -102,7 +102,7 @@ GeoPlot: `graticule sphere dot text vector link contour inset geo-hover geo-comp
102
102
 
103
103
  ## Docs (in `docs/`)
104
104
 
105
- `getting-started.md`, `concepts.md`, `plots.md` (an index: one page per plot kind in `plots/`), `scales.md`, `styles-and-segments.md`, `markers.md`, `transforms-and-statistics.md`, `tooltip-and-hover.md`, `legend.md`, `timeline.md`, `chrome.md`, `facets.md`, `composer.md`, `state.md`, `geo.md`, `theming.md`.
105
+ `getting-started.md`, `concepts.md`, `plots.md` (an index: one page per plot kind in `plots/`), `scales.md`, `styles-and-segments.md`, `value-labels.md`, `markers.md`, `transforms-and-statistics.md`, `tooltip-and-hover.md`, `legend.md`, `timeline.md`, `chrome.md`, `facets.md`, `composer.md`, `state.md`, `geo.md`, `theming.md`.
106
106
 
107
107
  ## Examples (in `examples/`, all runnable)
108
108
 
package/llms.txt CHANGED
@@ -33,6 +33,7 @@ Start with the full guide: it lists the mental model, the props every plot share
33
33
  - [ScatterPlot](./docs/plots/correlation/scatter.md)
34
34
  - [Scales](./docs/scales.md): axes and channel scales
35
35
  - [Styles and segments](./docs/styles-and-segments.md): value labels, frame, gaps, ranges of data
36
+ - [Value labels](./docs/value-labels.md): `styles.values` and a marker's `label`, their `'point'`, `'path'` and `'box'` layouts and options
36
37
  - [Markers](./docs/markers.md): annotations, regions, hover highlight, custom components
37
38
  - [Transforms and statistics](./docs/transforms-and-statistics.md): stacking, binning, smoothing, regression, and the statistics `regression`, `movingAverage`, `bollinger`, `density`, `density2d`, `box`, `deviation` with their options
38
39
  - [Tooltip and hover](./docs/tooltip-and-hover.md): tooltip options, hover marker, sync
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fundar/data-chart-telling",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "description": "Declarative charts, maps and small multiples for Svelte, built on svelteplot.",
5
5
  "license": "MIT",
6
6
  "author": "Ezequiel Puerta",
@@ -57,6 +57,7 @@
57
57
  "d3-interpolate": "^3.0.1",
58
58
  "d3-scale-chromatic": "^3.1.0",
59
59
  "d3-selection": "^3.0.0",
60
+ "d3-shape": "^3.2.0",
60
61
  "d3-zoom": "^3.0.0"
61
62
  },
62
63
  "peerDependencies": {
@@ -86,6 +87,7 @@
86
87
  "@types/d3-interpolate": "^3.0.4",
87
88
  "@types/d3-scale-chromatic": "^3.1.0",
88
89
  "@types/d3-selection": "^3.0.11",
90
+ "@types/d3-shape": "^3.2.0",
89
91
  "@types/d3-zoom": "^3.0.8",
90
92
  "@types/node": "^22",
91
93
  "@vitest/browser": "^4.1.7",