@fundar/data-chart-telling 1.16.0 → 1.17.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 (194) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/configuration/ConfigVars.svelte +14 -0
  3. package/dist/configuration/ConfigVars.svelte.d.ts +3 -0
  4. package/dist/configuration/config.svelte.d.ts +5 -0
  5. package/dist/configuration/config.svelte.js +17 -4
  6. package/dist/configuration/themes/dark.js +1 -1
  7. package/dist/configuration/themes/editorial.js +1 -1
  8. package/dist/index.d.ts +6 -3
  9. package/dist/index.js +2 -1
  10. package/dist/layout/base/BasePlotLayout.svelte +1 -1
  11. package/dist/layout/figure/Figure.svelte +5 -12
  12. package/dist/layout/figure/FigureChrome.svelte +2 -10
  13. package/dist/layout/geometry/GeometryLayout.svelte +42 -1
  14. package/dist/layout/hover/HoverSettings.d.ts +3 -1
  15. package/dist/layout/hover/HoverSettings.js +4 -2
  16. package/dist/layout/legend/DisabledStyle.d.ts +1 -1
  17. package/dist/layout/legend/DisabledStyle.js +1 -1
  18. package/dist/layout/legend/DiscreteBadgeItem.svelte +1 -1
  19. package/dist/layout/legend/DiscreteSection.svelte +1 -1
  20. package/dist/layout/legend/LegendState.svelte.d.ts +12 -2
  21. package/dist/layout/legend/LegendState.svelte.js +18 -4
  22. package/dist/layout/legend/LegendText.d.ts +4 -1
  23. package/dist/layout/legend/LegendText.js +7 -1
  24. package/dist/layout/margins/PlotMargins.svelte.d.ts +2 -2
  25. package/dist/layout/margins/PlotMargins.svelte.js +2 -2
  26. package/dist/layout/plot/Plot.svelte +4 -2
  27. package/dist/layout/plot/Plot.svelte.d.ts +2 -1
  28. package/dist/layout/scales/ScalesLayout.svelte +1 -1
  29. package/dist/layout/styles/ValueLabels.d.ts +33 -2
  30. package/dist/layout/styles/ValueLabels.js +67 -8
  31. package/dist/layout/timeline/Timeline.svelte +5 -1
  32. package/dist/markers/area/AreaMarker.svelte +3 -0
  33. package/dist/markers/arrow/ArrowMarker.svelte +9 -5
  34. package/dist/markers/bar/BarMarker.svelte +45 -48
  35. package/dist/markers/bollinger/BollingerMarker.svelte +3 -0
  36. package/dist/markers/box/BoxMarker.svelte +3 -1
  37. package/dist/markers/cell/CellMarker.svelte +11 -7
  38. package/dist/markers/contour/ContourMarker.svelte +3 -0
  39. package/dist/markers/delaunay/DelaunayLinkMarker.svelte +9 -5
  40. package/dist/markers/delaunay/DelaunayMeshMarker.svelte +3 -0
  41. package/dist/markers/density/DensityMarker.svelte +3 -0
  42. package/dist/markers/difference/DifferenceMarker.svelte +3 -0
  43. package/dist/markers/dot/DotMarker.svelte +11 -6
  44. package/dist/markers/geo/GraticuleMarker.svelte +3 -0
  45. package/dist/markers/geo/SphereMarker.svelte +3 -0
  46. package/dist/markers/hover/HoverMarker.svelte +22 -6
  47. package/dist/markers/hull/HullMarker.svelte +3 -0
  48. package/dist/markers/image/ImageMarker.svelte +3 -0
  49. package/dist/markers/line/LineMarker.svelte +3 -0
  50. package/dist/markers/link/LinkMarker.svelte +3 -0
  51. package/dist/markers/raster/RasterMarker.svelte +3 -0
  52. package/dist/markers/rect/RectMarker.svelte +25 -17
  53. package/dist/markers/regression/RegressionMarker.svelte +3 -0
  54. package/dist/markers/rule/RuleMarker.svelte +15 -5
  55. package/dist/markers/text/TextFit.d.ts +44 -0
  56. package/dist/markers/text/TextFit.js +86 -0
  57. package/dist/markers/text/TextMarker.svelte +186 -90
  58. package/dist/markers/text/TextMarker.svelte.d.ts +2 -0
  59. package/dist/markers/tick/TickMarker.svelte +9 -3
  60. package/dist/markers/trail/TrailMarker.svelte +3 -0
  61. package/dist/markers/utils/BoxLabel.d.ts +58 -0
  62. package/dist/markers/utils/BoxLabel.js +175 -0
  63. package/dist/markers/utils/MarkerEvents.d.ts +23 -0
  64. package/dist/markers/utils/MarkerEvents.js +44 -0
  65. package/dist/markers/utils/MarkerLabel.svelte +33 -0
  66. package/dist/markers/utils/MarkerLabel.svelte.d.ts +10 -0
  67. package/dist/markers/utils/RowStroke.d.ts +9 -21
  68. package/dist/markers/utils/RowStroke.js +10 -21
  69. package/dist/markers/utils/RowStyle.d.ts +26 -0
  70. package/dist/markers/utils/RowStyle.js +55 -0
  71. package/dist/markers/vector/VectorMarker.svelte +3 -0
  72. package/dist/markers/voronoi/VoronoiMarker.svelte +9 -5
  73. package/dist/markers/voronoi/VoronoiMeshMarker.svelte +3 -0
  74. package/dist/markers/waffle/WaffleMarker.svelte +9 -5
  75. package/dist/phases/Pipeline.d.ts +3 -1
  76. package/dist/phases/Pipeline.js +1 -0
  77. package/dist/phases/data/DataPhase.js +51 -10
  78. package/dist/phases/hover/HoverPhase.js +9 -1
  79. package/dist/phases/mapping/MappingPhase.js +2 -1
  80. package/dist/phases/markers/MarkerStyles.d.ts +18 -0
  81. package/dist/phases/markers/MarkerStyles.js +111 -0
  82. package/dist/phases/markers/MarkersPhase.d.ts +1 -1
  83. package/dist/phases/markers/MarkersPhase.js +7 -5
  84. package/dist/phases/statistics/StatisticsPhase.js +1 -1
  85. package/dist/phases/transforms/Transforms.js +3 -1
  86. package/dist/phases/transforms/TransformsPhase.js +58 -4
  87. package/dist/phases/transforms/methods/TreemapTransform.d.ts +28 -0
  88. package/dist/phases/transforms/methods/TreemapTransform.js +119 -0
  89. package/dist/plots/correlation/heatmap/defaults.js +2 -2
  90. package/dist/plots/correlation/heatmap/markers.d.ts +0 -8
  91. package/dist/plots/correlation/heatmap/markers.js +8 -35
  92. package/dist/plots/correlation/scatter/markers.d.ts +1 -1
  93. package/dist/plots/correlation/scatter/markers.js +2 -2
  94. package/dist/plots/distribution/histogram/defaults.js +2 -2
  95. package/dist/plots/distribution/histogram/markers.d.ts +1 -10
  96. package/dist/plots/distribution/histogram/markers.js +17 -59
  97. package/dist/plots/distribution/pyramid/defaults.js +3 -3
  98. package/dist/plots/distribution/pyramid/markers.d.ts +0 -10
  99. package/dist/plots/distribution/pyramid/markers.js +13 -64
  100. package/dist/plots/distribution/violin/markers.js +1 -1
  101. package/dist/plots/map/geo/phases/markers.js +3 -2
  102. package/dist/plots/part-of-a-whole/treemap/Plot.svelte +47 -0
  103. package/dist/plots/part-of-a-whole/treemap/Plot.svelte.d.ts +26 -0
  104. package/dist/plots/part-of-a-whole/treemap/defaults.d.ts +10 -0
  105. package/dist/plots/part-of-a-whole/treemap/defaults.js +167 -0
  106. package/dist/plots/ranking/bar/defaults.js +2 -2
  107. package/dist/plots/ranking/bar/markers.d.ts +1 -11
  108. package/dist/plots/ranking/bar/markers.js +38 -80
  109. package/dist/plots/ranking/bullet/markers.js +2 -3
  110. package/dist/plots/ranking/cleveland/ClevelandMarkers.js +17 -13
  111. package/dist/types/configuration/styling.d.ts +27 -2
  112. package/dist/types/layout/legend.d.ts +8 -1
  113. package/dist/types/layout/mapping.d.ts +12 -3
  114. package/dist/types/layout/scales.d.ts +6 -0
  115. package/dist/types/layout/tooltip.d.ts +16 -4
  116. package/dist/types/markers/axis/arrow.d.ts +2 -8
  117. package/dist/types/markers/axis/bar.d.ts +4 -8
  118. package/dist/types/markers/axis/cell.d.ts +5 -5
  119. package/dist/types/markers/axis/delaunayLink.d.ts +2 -2
  120. package/dist/types/markers/axis/rect.d.ts +4 -8
  121. package/dist/types/markers/axis/rule.d.ts +2 -16
  122. package/dist/types/markers/axis/tick.d.ts +2 -2
  123. package/dist/types/markers/axis/voronoi.d.ts +2 -2
  124. package/dist/types/markers/axis/waffle.d.ts +4 -3
  125. package/dist/types/markers/basic/dot.d.ts +2 -2
  126. package/dist/types/markers/basic/text.d.ts +56 -14
  127. package/dist/types/markers/channels/commonMarkerConfig.d.ts +4 -1
  128. package/dist/types/markers/channels/commonMarkerConfigWithArea.d.ts +1 -2
  129. package/dist/types/markers/channels/commonMarkerConfigWithLabel.d.ts +10 -0
  130. package/dist/types/markers/channels/commonMarkerConfigWithLabel.js +1 -0
  131. package/dist/types/markers/channels/commonMarkerEvents.d.ts +17 -0
  132. package/dist/types/markers/channels/commonMarkerEvents.js +13 -0
  133. package/dist/types/markers/geo/contour.d.ts +2 -1
  134. package/dist/types/markers/geo/graticule.d.ts +2 -1
  135. package/dist/types/markers/geo/link.d.ts +2 -1
  136. package/dist/types/markers/geo/sphere.d.ts +2 -1
  137. package/dist/types/markers/geo/vector.d.ts +2 -1
  138. package/dist/types/phases/data/phase.d.ts +5 -0
  139. package/dist/types/phases/hover/phase.d.ts +2 -0
  140. package/dist/types/phases/state.d.ts +7 -0
  141. package/dist/types/phases/statistics/phase.d.ts +2 -1
  142. package/dist/types/phases/transforms/phase.d.ts +11 -0
  143. package/dist/types/plots/constants.d.ts +14 -14
  144. package/dist/types/plots/correlation/heatmap/props.d.ts +3 -3
  145. package/dist/types/plots/correlation/scatter/props.d.ts +3 -3
  146. package/dist/types/plots/data/common.d.ts +19 -6
  147. package/dist/types/plots/data/geo.d.ts +1 -1
  148. package/dist/types/plots/distribution/box/props.d.ts +3 -3
  149. package/dist/types/plots/distribution/density/props.d.ts +3 -11
  150. package/dist/types/plots/distribution/histogram/props.d.ts +3 -11
  151. package/dist/types/plots/distribution/pyramid/props.d.ts +3 -3
  152. package/dist/types/plots/distribution/violin/props.d.ts +3 -3
  153. package/dist/types/plots/evolution/area/props.d.ts +3 -3
  154. package/dist/types/plots/evolution/line/props.d.ts +3 -3
  155. package/dist/types/plots/part-of-a-whole/treemap/props.d.ts +19 -0
  156. package/dist/types/plots/part-of-a-whole/treemap/props.js +1 -0
  157. package/dist/types/plots/part-of-a-whole/treemap/state.d.ts +6 -0
  158. package/dist/types/plots/part-of-a-whole/treemap/state.js +1 -0
  159. package/dist/types/plots/props.d.ts +7 -4
  160. package/dist/types/plots/ranking/bar/props.d.ts +3 -3
  161. package/dist/types/plots/ranking/cleveland/props.d.ts +3 -3
  162. package/dist/types/plots/ranking/dumbbell/props.d.ts +3 -3
  163. package/dist/types/plots/ranking/forest/props.d.ts +3 -3
  164. package/dist/types/plots/ranking/lollipop/props.d.ts +3 -3
  165. package/dist/types/plots/styling.d.ts +24 -0
  166. package/dist/types/transforms/index.d.ts +3 -1
  167. package/dist/types/transforms/treemap.d.ts +32 -0
  168. package/dist/types/transforms/treemap.js +5 -0
  169. package/dist/utils/color/ColorTones.d.ts +19 -0
  170. package/dist/utils/color/ColorTones.js +64 -0
  171. package/dist/utils/color/CssColor.d.ts +14 -5
  172. package/dist/utils/color/CssColor.js +69 -27
  173. package/dist/utils/color/index.d.ts +4 -0
  174. package/dist/utils/color/index.js +4 -0
  175. package/dist/utils/grouping.d.ts +18 -1
  176. package/dist/utils/grouping.js +31 -0
  177. package/docs/concepts.md +3 -2
  178. package/docs/legend.md +8 -5
  179. package/docs/markers.md +76 -26
  180. package/docs/plots/part-of-a-whole/treemap.md +69 -0
  181. package/docs/plots/ranking/bar.md +1 -1
  182. package/docs/plots.md +21 -20
  183. package/docs/scales.md +3 -0
  184. package/docs/state.md +1 -1
  185. package/docs/styles-and-segments.md +19 -18
  186. package/docs/theming.md +4 -11
  187. package/docs/tooltip-and-hover.md +1 -1
  188. package/docs/transforms-and-statistics.md +17 -16
  189. package/examples/Treemap.svelte +13 -0
  190. package/examples/datasets/economic-activity.ts +40 -0
  191. package/examples/datasets/index.ts +1 -0
  192. package/llms-full.txt +5 -5
  193. package/llms.txt +2 -0
  194. package/package.json +3 -1
@@ -66,77 +66,6 @@ hover, ctx) {
66
66
  };
67
67
  });
68
68
  }
69
- /**
70
- * BarPlot's `styles.values` as one `'text'` marker per series, over the same
71
- * processed rows its bars draw (gap rows never get a label). `anchor` places
72
- * each label along its bar: past its top (`'outside'`), just inside it
73
- * (`'start'`), at its base (`'end'`), or centred (`'middle'`); a stacked bar's
74
- * label always sits at the middle of its own span. A grouped bar's label
75
- * shifts with its series' slice of the band.
76
- */
77
- export function buildValueLabels(labels, state, ctx) {
78
- const { processedData } = state;
79
- const isHorizontal = state.axes?.isHorizontal ?? false;
80
- if (!processedData)
81
- return [];
82
- const geometry = buildBarGeometry(state, ctx.cfg.bar.seriesPadding);
83
- const { font, anchor, format } = labels;
84
- const valueOf = ValueLabels.valueOf(state);
85
- const spanOf = (d) => geometry.spanOf(d) ?? [0, 0];
86
- const lowOf = (d) => Math.min(...spanOf(d));
87
- const highOf = (d) => Math.max(...spanOf(d));
88
- const below = (d) => Number(valueOf(d)) < 0;
89
- const place = (negative) => {
90
- const mid = (d) => (lowOf(d) + highOf(d)) / 2;
91
- if (geometry.stacked)
92
- return { at: mid, side: 0 };
93
- if (anchor === 'middle')
94
- return { at: mid, side: 0 };
95
- if (anchor === 'outside')
96
- return isHorizontal
97
- ? { at: negative ? lowOf : highOf, side: negative ? -1 : 1 }
98
- : { at: negative ? lowOf : highOf, side: negative ? 1 : -1 };
99
- if (anchor === 'start')
100
- return isHorizontal ? { at: lowOf, side: 1 } : { at: highOf, side: 1 };
101
- return isHorizontal ? { at: highOf, side: -1 } : { at: lowOf, side: -1 };
102
- };
103
- const gap = anchor === 'outside' ? 6 : 4;
104
- const labelled = processedData.data.filter((d) => d[GAP_VALUE] === undefined && geometry.spanOf(d) !== undefined);
105
- return (state.resolvedSeries ?? []).flatMap((s) => {
106
- const own = labelled.filter((d) => d[SERIES_ID_KEY] === seriesIdOf(s));
107
- // Only a label beyond the tip turns with the sign of its value.
108
- const turns = !geometry.stacked && anchor === 'outside';
109
- return (turns ? [false, true] : [false]).flatMap((negative) => {
110
- const data = turns ? own.filter((d) => below(d) === negative) : own;
111
- if (data.length === 0)
112
- return [];
113
- const { at, side } = place(negative);
114
- // A horizontal label reads away from its point to `side`; a vertical one sits on the far side of it.
115
- const textAnchor = labels.textAnchor ??
116
- (isHorizontal ? (side === 1 ? 'start' : side === -1 ? 'end' : 'middle') : 'middle');
117
- const lineAnchor = font?.lineAnchor ??
118
- (isHorizontal ? 'middle' : side === 1 ? 'top' : side === -1 ? 'bottom' : 'middle');
119
- return [
120
- {
121
- type: 'text',
122
- data,
123
- ...(isHorizontal ? { x: at, y: geometry.categoryOf } : { x: geometry.categoryOf, y: at }),
124
- bandSlice: geometry.sliceOf(s.name),
125
- text: (d) => format(Number(valueOf(d)), s.name, d),
126
- styles: {
127
- ...font,
128
- fill: font?.fill ?? ctx.cfg.axis.color,
129
- fontSize: font?.fontSize ?? 12,
130
- dx: font?.dx ?? (isHorizontal ? side * gap : 0),
131
- dy: font?.dy ?? (isHorizontal ? 0 : side * gap),
132
- textAnchor,
133
- lineAnchor
134
- }
135
- }
136
- ];
137
- });
138
- });
139
- }
140
69
  /**
141
70
  * BarPlot's "markers" phase: visible `role: 'segment'` bars - real data plus
142
71
  * gap fills - drawing the rows the "transforms" phase left, prepended onto
@@ -160,7 +89,25 @@ export function buildMarks(state, ctx) {
160
89
  // which stays a field key whenever the plot has no transforms.
161
90
  const valueOf = (channel) => (geometry.stacked || channel === undefined ? top : channel);
162
91
  const gapValue = valueOf(channels[valueAxis]);
163
- function makeMarker(data, slice, value, styles) {
92
+ // What each bar writes in itself: its value, anchored along the bar by `anchor` - past its tip
93
+ // (`'outside'`), just inside it (`'start'`), at its base (`'end'`) or in the middle. A stacked bar's
94
+ // label is always in the middle of its segment.
95
+ const labels = state.valueLabels?.show ? state.valueLabels : undefined;
96
+ const valueRead = ValueLabels.valueOf(state);
97
+ const turns = !!labels && !geometry.stacked && ValueLabels.followsSign(labels.anchor);
98
+ const labelAnchor = (negative) => ValueLabels.boxAnchor(labels?.anchor ?? 'outside', {
99
+ isHorizontal,
100
+ negative,
101
+ stacked: geometry.stacked
102
+ });
103
+ const labelFor = (name, slice, negative) => labels && {
104
+ ...labels.shapeLabel(ctx, (d) => labels.format(Number(valueRead(d)), name, d), {
105
+ fill: 'currentColor',
106
+ ...labelAnchor(negative)
107
+ }),
108
+ bandSlice: slice
109
+ };
110
+ function makeMarker(data, slice, value, styles, label) {
164
111
  if (data.length === 0)
165
112
  return null;
166
113
  const from = (geometry.stacked ? bottom : geometry.baseline);
@@ -170,18 +117,17 @@ export function buildMarks(state, ctx) {
170
117
  isHorizontal,
171
118
  data,
172
119
  styles,
120
+ ...(label ? { label } : {}),
173
121
  ...(isHorizontal
174
122
  ? { y: category, x1: from, x2: value }
175
123
  : { x: category, y1: from, y2: value })
176
124
  };
177
125
  if (slice) {
178
126
  if (isHorizontal) {
179
- marker.insetTop = slice.start;
180
- marker.insetBottom = slice.end;
127
+ marker.styles = { ...marker.styles, insetTop: slice.start, insetBottom: slice.end };
181
128
  }
182
129
  else {
183
- marker.insetLeft = slice.start;
184
- marker.insetRight = slice.end;
130
+ marker.styles = { ...marker.styles, insetLeft: slice.start, insetRight: slice.end };
185
131
  }
186
132
  }
187
133
  return marker;
@@ -195,7 +141,7 @@ export function buildMarks(state, ctx) {
195
141
  const disabledFill = ctx.interaction?.fillFor(name);
196
142
  for (const seg of group.visualSegments) {
197
143
  const fill = disabledFill?.fill ?? seg.styles.fill ?? defaultColor;
198
- const marker = makeMarker(seg.data.filter(isReal), slice, valueOf(group.series[valueAxis]), {
144
+ const styles = {
199
145
  // An outline asked for without a color is the fill's.
200
146
  ...(seg.styles.strokeWidth !== undefined ? { stroke: fill } : {}),
201
147
  ...seg.styles,
@@ -205,9 +151,21 @@ export function buildMarks(state, ctx) {
205
151
  ...(disabledFill?.fillOpacity !== undefined
206
152
  ? { strokeOpacity: disabledFill.fillOpacity }
207
153
  : {})
208
- });
209
- if (marker)
210
- segmentMarkers.push(marker);
154
+ };
155
+ const real = seg.data.filter(isReal);
156
+ const value = valueOf(group.series[valueAxis]);
157
+ // A label past the tip turns with the sign of its value, so the bars below zero are a marker of their own.
158
+ const parts = turns
159
+ ? [false, true].map((negative) => ({
160
+ negative,
161
+ rows: real.filter((row) => Number(valueRead(row)) < 0 === negative)
162
+ }))
163
+ : [{ negative: false, rows: real }];
164
+ for (const { negative, rows } of parts) {
165
+ const marker = makeMarker(rows, slice, value, styles, labelFor(name, slice, negative));
166
+ if (marker)
167
+ segmentMarkers.push(marker);
168
+ }
211
169
  }
212
170
  const id = seriesIdOf(group.series);
213
171
  const fills = [...(gapFillMaps.get(id)?.values() ?? [])];
@@ -33,7 +33,7 @@ export function buildMarks(state, ctx) {
33
33
  const rangeColors = own.ranges?.colors ?? configured.rangeColors;
34
34
  const rangeWidth = own.ranges?.width ?? configured.rangeWidth;
35
35
  const target = {
36
- color: own.target?.color ?? configured.targetColor ?? ctx.cfg.axis.color,
36
+ color: own.target?.color ?? configured.targetColor ?? 'currentColor',
37
37
  width: own.target?.width ?? configured.targetWidth,
38
38
  length: own.target?.length ?? configured.targetLength
39
39
  };
@@ -59,8 +59,7 @@ export function buildMarks(state, ctx) {
59
59
  data: rows,
60
60
  value: 'category',
61
61
  ...(isHorizontal ? { x1: 'from', x2: 'to' } : { y1: 'from', y2: 'to' }),
62
- stroke: 'stroke',
63
- styles: { strokeWidth: rangeWidth }
62
+ styles: { stroke: 'stroke', strokeWidth: rangeWidth }
64
63
  }
65
64
  ];
66
65
  // The bars narrowed to a thickness of their own, centered in their band.
@@ -45,7 +45,7 @@ export class ClevelandMarkers {
45
45
  // color and its segment's style; the legend dims it with the series.
46
46
  const size = state.channels?.r;
47
47
  const dotRadius = typeof size === 'number' ? size : style.dotRadius;
48
- const neutral = style.connectorColor ?? cfg.axis.color;
48
+ const neutral = style.connectorColor ?? 'currentColor';
49
49
  // `styles.stroke` is the connectors' look below everything the author sets for them: a segment's
50
50
  // stroke wins over `styles.connector`, which wins over it. A function of the series styles only
51
51
  // the connector of a lone dot, which has a series; the connector of several dots has none.
@@ -135,10 +135,12 @@ export class ClevelandMarkers {
135
135
  data: group.flatMap((look) => look.rows),
136
136
  value: 'category',
137
137
  ...(isHorizontal ? { x1: 'from', x2: 'to' } : { y1: 'from', y2: 'to' }),
138
- stroke: 'stroke',
139
- strokeWidth: 'strokeWidth',
140
- strokeOpacity: 'strokeOpacity',
141
- ...(Object.keys(pattern).length > 0 ? { styles: pattern } : {})
138
+ styles: {
139
+ ...pattern,
140
+ stroke: 'stroke',
141
+ strokeWidth: 'strokeWidth',
142
+ strokeOpacity: 'strokeOpacity'
143
+ }
142
144
  }));
143
145
  // The arrows, one marker per pattern like the lines, each from its `from` dot to its `to` dot.
144
146
  const head = connector.arrow;
@@ -157,12 +159,14 @@ export class ClevelandMarkers {
157
159
  headLength: head.headLength,
158
160
  headAngle: head.headAngle,
159
161
  // The shaft starts and ends at the edge of its dots, not under them.
160
- insetStart: dotRadius,
161
- insetEnd: dotRadius,
162
- stroke: 'stroke',
163
- strokeWidth: 'strokeWidth',
164
- strokeOpacity: 'strokeOpacity',
165
- ...(Object.keys(pattern).length > 0 ? { styles: pattern } : {})
162
+ styles: {
163
+ ...pattern,
164
+ insetStart: dotRadius,
165
+ insetEnd: dotRadius,
166
+ stroke: 'stroke',
167
+ strokeWidth: 'strokeWidth',
168
+ strokeOpacity: 'strokeOpacity'
169
+ }
166
170
  }
167
171
  ];
168
172
  });
@@ -266,7 +270,7 @@ export class ClevelandMarkers {
266
270
  text: 'text',
267
271
  styles: {
268
272
  ...font,
269
- fill: font?.fill ?? ctx.cfg.axis.color,
273
+ fill: font?.fill ?? 'currentColor',
270
274
  fontSize: font?.fontSize ?? ctx.cfg.connector.labelFontSize,
271
275
  dx: font?.dx ?? at.dx,
272
276
  dy: font?.dy ?? at.dy,
@@ -308,7 +312,7 @@ export class ClevelandMarkers {
308
312
  // What fills the labels of a series: the one fill all share, its own color, or the axis'.
309
313
  const fillOf = (series) => labels.fill ??
310
314
  (labels.color === 'series' ? state.colorForSeries(series) : undefined) ??
311
- ctx.cfg.axis.color;
315
+ 'currentColor';
312
316
  const names = labels.color === 'series' && !labels.fill
313
317
  ? (state.resolvedSeries ?? []).map((s) => s.name)
314
318
  : [''];
@@ -70,7 +70,7 @@ export type PlotStylesConfig = {
70
70
  palette: string[];
71
71
  /** Default shape cycle for the `symbol` channel, in order. */
72
72
  symbols: SymbolType[];
73
- /** The default continuous ramp, the on-cell label colour and the default opacity-channel range. */
73
+ /** The default continuous ramp and the default opacity-channel range. */
74
74
  continuous: {
75
75
  /** The ramp's first color, when it is not a named `scheme`. */
76
76
  min: string;
@@ -80,7 +80,6 @@ export type PlotStylesConfig = {
80
80
  scheme?: string;
81
81
  /** The part of `scheme` to use, as `[from, to]` fractions of it: `[0.2, 1]` skips the near-white start of `'blues'`. */
82
82
  schemeRange?: [number, number];
83
- labelColor: string;
84
83
  opacityRange: [number, number];
85
84
  };
86
85
  /**
@@ -264,6 +263,19 @@ export type PlotStylesConfig = {
264
263
  disabledOpacity: number;
265
264
  };
266
265
  };
266
+ /** The tiles of a `TreemapPlot` and the labels written on them. */
267
+ treemap: {
268
+ /** The line between tiles. */
269
+ stroke: string;
270
+ /** Its width, in px. */
271
+ strokeWidth: number;
272
+ /** Font size of a tile's label, in px. */
273
+ fontSize: number;
274
+ /** The room kept between a tile's edge and its label, in px. */
275
+ padding: number;
276
+ /** Line height of a tile's label, as a multiple of its font size. */
277
+ lineHeight: number;
278
+ };
267
279
  /** Timeline gutter styling. */
268
280
  timeline: {
269
281
  axisColor: string;
@@ -378,6 +390,19 @@ export type PlotStylesConfig = {
378
390
  };
379
391
  /** Default text-marker behavior. */
380
392
  text: {
393
+ /** Defaults of the `label` a shape writes in itself (`rect`, `cell`, `bar`, `waffle`), each overridden by the label's own `gap` and `fit`. */
394
+ label: {
395
+ /** Pixels between a label and the edge it is anchored to. */
396
+ gap: number;
397
+ /** Pixels a fitted label keeps free inside each edge of its shape. */
398
+ padding: number;
399
+ /** The smallest size a fitted label is written at, in px. */
400
+ minFontSize: number;
401
+ /** The fewest letters worth writing when a fitted label is cut short; under them its `fallback` is written. */
402
+ minLetters: number;
403
+ /** The colors a label inside its shape is written in: the one that reads best on the shape's color. A label's own `fill` wins. */
404
+ contrast: string[];
405
+ };
381
406
  /** Geometry and connector of a decluttered text marker (`declutter`) - e.g. LinePlot's end-of-line value labels. */
382
407
  declutter: {
383
408
  /** Shortest lane's distance (px) from the point before a connector bends. */
@@ -20,7 +20,12 @@ export type LegendDisabledStyle = {
20
20
  * What a legend toggle does to a series once it's off: `'dim'` dims it in
21
21
  * place (styled by `style`), `'hide'` makes it fully transparent while the
22
22
  * axes keep its range, `'omit'` removes it from the plot entirely, rescaling
23
- * the axes to what's left.
23
+ * the axes to what's left - the other series keep their values, and a part of
24
+ * a whole (a treemap's tile) its share and its place. `'rescale'` removes it
25
+ * too, and the parts left make the whole again: a stack's visible parts are
26
+ * scaled up to the total each category had, and a treemap's tiles are laid out
27
+ * and given their shares anew, as the new 100%. On a plot of no parts it is an
28
+ * `'omit'`.
24
29
  */
25
30
  export type LegendDisabledAction = {
26
31
  mode: 'dim';
@@ -29,6 +34,8 @@ export type LegendDisabledAction = {
29
34
  mode: 'hide';
30
35
  } | {
31
36
  mode: 'omit';
37
+ } | {
38
+ mode: 'rescale';
32
39
  };
33
40
  export type LegendItem = {
34
41
  name: string;
@@ -14,7 +14,9 @@ export type ChannelValue = {
14
14
  * Splits `data` into one series per distinct value - the structural
15
15
  * grouping key. Defaults to `color` when omitted, so a single `color`
16
16
  * accessor groups *and* colors series; pass both to split by one field
17
- * while coloring by another.
17
+ * while coloring by another. A dotted name (`'sector.branch'`) groups by several
18
+ * levels, outermost first: a plot that nests (a treemap) nests by them, any other
19
+ * splits by their combination - see {@link GroupingAccessor}.
18
20
  */
19
21
  grouping: unknown;
20
22
  /**
@@ -34,6 +36,8 @@ export type ChannelValue = {
34
36
  r: number;
35
37
  /** Vector/spike magnitude - a literal number is a fixed pixel length. Configure via `scales.length`. */
36
38
  length: number;
39
+ /** What a row amounts to as a part of a whole: a treemap tile's area. A plot without parts ignores it. */
40
+ value: number;
37
41
  };
38
42
  /** Every channel a plot maps from its rows. */
39
43
  export type ChannelName = keyof ChannelValue;
@@ -46,9 +50,14 @@ export type AxisChannelName = 'x' | 'y';
46
50
  export type IndependentChannelName = 'color' | 'grouping' | 'opacity' | 'symbol';
47
51
  /** The size channels, which also take a literal number as a fixed pixel size that bypasses their scale. */
48
52
  export type SizeChannelName = 'r' | 'length';
49
- /** Every channel as a plot prop: a field key or accessor function (or a literal size, for a size channel). */
53
+ /**
54
+ * What a plot's rows group by: a field, the fields of several levels joined by dots (`'sector.branch'`,
55
+ * outermost first), or a function of the row. A dotted name is a field when the rows have one by that name.
56
+ */
57
+ export type GroupingAccessor<TData> = (keyof TData & string) | `${keyof TData & string}.${string}` | ((row: TData) => unknown);
58
+ /** Every channel as a plot prop: a field key or accessor function (or a literal size, for a size channel); `grouping` also takes levels - see {@link GroupingAccessor}. */
50
59
  export type ChannelAccessors<TData extends Record<string, unknown>> = {
51
- [K in keyof ChannelValue]?: Accessor<TData, ChannelValue[K]> | (K extends SizeChannelName ? number : never);
60
+ [K in keyof ChannelValue]?: K extends 'grouping' ? GroupingAccessor<TData> : Accessor<TData, ChannelValue[K]> | (K extends SizeChannelName ? number : never);
52
61
  };
53
62
  /** One channel's own resolved data accessor - mirrors svelteplot's own `ChannelAccessor`. */
54
63
  export type ResolvedChannel<TData, TValue = AxisValue> = {
@@ -19,6 +19,12 @@ export type ColorScaleConfig = {
19
19
  pivot?: number;
20
20
  /** Fallback color for a missing/unmapped value. Defaults to `'#ccc'`. */
21
21
  unknown?: string;
22
+ /**
23
+ * With a `grouping` of several levels (`'sector.kind.branch'`), the level its colors reach: `1` (the default)
24
+ * gives each outermost value its color, and a deeper one gives each value down to that level a tone of its
25
+ * outermost value's color - `2` a tone per kind within its sector's color. Ignored by a continuous ramp.
26
+ */
27
+ depth?: number;
22
28
  };
23
29
  /** How groups sharing the same `grouping`/`color` value are ordered: `reverse` flips which sorts first (e.g. PyramidPlot's left/right sides). */
24
30
  export type GroupingScaleConfig = {
@@ -12,18 +12,30 @@ export type TooltipAnchorY = 'top' | 'middle' | 'bottom';
12
12
  export type TooltipRow<TRow> = TRow & {
13
13
  seriesColor?: string;
14
14
  };
15
+ /**
16
+ * What a plot knows of a hovered row beyond its own fields, the third argument of a tooltip's `format`:
17
+ * the series it is drawn in, on the plots that have series. A plot kind that works out more about a row
18
+ * gives a type that extends this one.
19
+ */
20
+ export type TooltipContext = {
21
+ /** The name of the series the row is drawn in. */
22
+ series?: string;
23
+ };
15
24
  /**
16
25
  * Author-facing tooltip option on the chart kinds. `true` = enable with defaults. `decimals`, `prefix`,
17
26
  * `suffix` and `signDisplay` write the value the default text shows - the one on the plot's value axis (the
18
27
  * x of a horizontal bar chart), and a heatmap's color value - and the numbers a custom `format` writes with its `number`.
19
28
  */
20
- export type TooltipOptions<TRow extends Record<string, unknown>> = NumberDisplay & {
29
+ export type TooltipOptions<TRow extends Record<string, unknown>, TContext extends TooltipContext = TooltipContext> = NumberDisplay & {
21
30
  /** Matching strategy. Defaults to the chart kind's own default. */
22
31
  strategy?: HoverStrategy;
23
32
  /** Highlight the hovered point in every synced plot too. Defaults to `false`. */
24
33
  sync?: boolean;
25
- /** Custom tooltip text for a row (supports `\n`). Defaults per chart kind. `number` writes a value as the display fields above ask. */
26
- format?: (row: TRow, number: (value: number) => string) => string;
34
+ /**
35
+ * Custom tooltip text for a row (supports `\n`). Defaults per chart kind. `number` writes a value as the display
36
+ * fields above ask, and `context` is what the plot knows of the row - see {@link TooltipContext}.
37
+ */
38
+ format?: (row: TRow, number: (value: number) => string, context: TContext) => string;
27
39
  /** Named subset of crossing series to include. Omitted = all matched. */
28
40
  series?: string[];
29
41
  /** Custom tooltip body; replaces `format` when given. Its rows carry a `seriesColor` - see {@link TooltipRow}. */
@@ -36,4 +48,4 @@ export type TooltipOptions<TRow extends Record<string, unknown>> = NumberDisplay
36
48
  anchorY?: TooltipAnchorY;
37
49
  };
38
50
  /** Either a bare on/off flag or the full option object. */
39
- export type TooltipProp<TRow extends Record<string, unknown>> = boolean | TooltipOptions<TRow>;
51
+ export type TooltipProp<TRow extends Record<string, unknown>, TContext extends TooltipContext = TooltipContext> = boolean | TooltipOptions<TRow, TContext>;
@@ -1,4 +1,4 @@
1
- import type { StrokeStyle } from '../../plots/styling';
1
+ import type { StrokeStyle, PerRow, DirectedInsetStyle } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithInterval } from '../channels/commonMarkerConfigWithInterval';
3
3
  /** A point-to-point arrow (svelteplot's `Arrow`), from `x1`/`y1` to `x2`/`y2`. */
4
4
  export type ArrowMarkerConfig = {
@@ -7,12 +7,6 @@ export type ArrowMarkerConfig = {
7
7
  bend?: number | true;
8
8
  headAngle?: number;
9
9
  headLength?: number;
10
- inset?: number;
11
- insetStart?: number;
12
- insetEnd?: number;
13
10
  sweep?: 1 | 0 | -1 | '+x' | '-x' | '+y' | '-y';
14
- stroke?: string | ((d: any) => string | undefined);
15
- strokeWidth?: string | ((d: any) => number);
16
- strokeOpacity?: string | ((d: any) => number);
17
- styles?: StrokeStyle;
11
+ styles?: PerRow<StrokeStyle & DirectedInsetStyle>;
18
12
  } & CommonMarkerConfigWithInterval;
@@ -1,5 +1,6 @@
1
1
  import type { AxisValue } from '../../layout/mapping';
2
- import type { AreaStyle } from '../../plots/styling';
2
+ import type { AreaStyle, PerRow, InsetStyle } from '../../plots/styling';
3
+ import type { CommonMarkerConfigWithLabel } from '../channels/commonMarkerConfigWithLabel';
3
4
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
4
5
  import type { CommonMarkerConfigWithInterval } from '../channels/commonMarkerConfigWithInterval';
5
6
  /** A bar mark; `role` tells a visible segment from the hover hit area and highlight. */
@@ -7,12 +8,7 @@ export type BarMarkerConfig = {
7
8
  type: 'bar';
8
9
  role: 'segment' | 'hitArea' | 'highlight';
9
10
  isHorizontal: boolean;
10
- insetTop?: number;
11
- insetBottom?: number;
12
- insetLeft?: number;
13
- insetRight?: number;
14
11
  thickness?: number;
15
- styles?: AreaStyle;
12
+ styles?: PerRow<AreaStyle> & InsetStyle;
16
13
  category?: AxisValue;
17
- hover?: boolean;
18
- } & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval;
14
+ } & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval & CommonMarkerConfigWithLabel;
@@ -1,9 +1,9 @@
1
- import type { AreaStyle } from '../../plots/styling';
1
+ import type { AreaStyle, PerRow, InsetStyle } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithArea } from '../channels/commonMarkerConfigWithArea';
3
+ import type { CommonMarkerConfigWithLabel } from '../channels/commonMarkerConfigWithLabel';
3
4
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
4
- /** A heatmap cell mark; `fill` is always set per row. */
5
+ /** A heatmap cell mark; its `fill` is set per row, by `color` or `styles.fill`. */
5
6
  export type CellMarkerConfig = {
6
7
  type: 'cell';
7
- styles?: AreaStyle;
8
- inset?: number;
9
- } & CommonMarkerConfigWithColor & Required<Pick<CommonMarkerConfigWithArea, 'fill'>>;
8
+ styles?: PerRow<AreaStyle & Pick<InsetStyle, 'inset'>>;
9
+ } & CommonMarkerConfigWithColor & CommonMarkerConfigWithArea & CommonMarkerConfigWithLabel;
@@ -1,7 +1,7 @@
1
- import type { AreaStyle } from '../../plots/styling';
1
+ import type { AreaStyle, PerRow } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
3
3
  /** One line per Delaunay triangulation edge (svelteplot's `DelaunayLink`). */
4
4
  export type DelaunayLinkMarkerConfig = {
5
5
  type: 'delaunayLink';
6
- styles?: AreaStyle;
6
+ styles?: PerRow<AreaStyle>;
7
7
  } & CommonMarkerConfigWithColor;
@@ -1,15 +1,11 @@
1
- import type { AreaStyle } from '../../plots/styling';
1
+ import type { AreaStyle, PerRow, InsetStyle } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithArea } from '../channels/commonMarkerConfigWithArea';
3
3
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
4
+ import type { CommonMarkerConfigWithLabel } from '../channels/commonMarkerConfigWithLabel';
4
5
  import type { CommonMarkerConfigWithInterval } from '../channels/commonMarkerConfigWithInterval';
5
6
  /** An arbitrary rectangle (svelteplot's `Rect`); `interval` turns `x`/`y` into ranges. */
6
7
  export type RectMarkerConfig = {
7
8
  type: 'rect';
8
9
  interval?: number | string;
9
- /** Pixels taken off each side of every rectangle; a bin's default `0.5` on each side leaves a hairline gap. */
10
- insetLeft?: number;
11
- insetRight?: number;
12
- insetTop?: number;
13
- insetBottom?: number;
14
- styles?: AreaStyle;
15
- } & CommonMarkerConfigWithArea & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval;
10
+ styles?: PerRow<AreaStyle & InsetStyle>;
11
+ } & CommonMarkerConfigWithArea & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval & CommonMarkerConfigWithLabel;
@@ -1,5 +1,5 @@
1
1
  import type { AxisValue } from '../../layout/mapping';
2
- import type { StrokeStyle } from '../../plots/styling';
2
+ import type { StrokeStyle, PerRow, InsetStyle } from '../../plots/styling';
3
3
  import type { CommonMarkerConfigWithInterval } from '../channels/commonMarkerConfigWithInterval';
4
4
  /**
5
5
  * A vertical or horizontal reference line, one line per row when `data` is given, or one per value
@@ -13,19 +13,5 @@ export type RuleMarkerConfig = {
13
13
  * a field key or a function of the row gives each row's own.
14
14
  */
15
15
  value: AxisValue | string | (AxisValue | string)[] | ((d: any) => AxisValue);
16
- inset?: number;
17
- insetTop?: number;
18
- insetBottom?: number;
19
- insetLeft?: number;
20
- insetRight?: number;
21
- /**
22
- * A stroke color for each row - a field key or a function of the row - drawn
23
- * as it is, not mapped through a color scale. Wins over `styles.stroke`.
24
- */
25
- stroke?: string | ((d: any) => string | undefined);
26
- /** A stroke width for each row - a field key or a function of the row. Wins over `styles.strokeWidth`. */
27
- strokeWidth?: string | ((d: any) => number);
28
- /** A stroke opacity for each row - a field key or a function of the row - drawn as it is. Wins over `styles.strokeOpacity`. */
29
- strokeOpacity?: string | ((d: any) => number);
30
- styles?: StrokeStyle;
16
+ styles?: PerRow<StrokeStyle & InsetStyle>;
31
17
  } & CommonMarkerConfigWithInterval;
@@ -1,8 +1,8 @@
1
- import type { StrokeStyle } from '../../plots/styling';
1
+ import type { StrokeStyle, PerRow } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
3
3
  /** A short tick per row along one axis (svelteplot's `TickX`/`TickY`). */
4
4
  export type TickMarkerConfig = {
5
5
  type: 'tick';
6
6
  tickLength?: number | ((d: any) => number);
7
- styles?: StrokeStyle;
7
+ styles?: PerRow<StrokeStyle>;
8
8
  } & CommonMarkerConfigWithColor;
@@ -1,7 +1,7 @@
1
- import type { AreaStyle } from '../../plots/styling';
1
+ import type { AreaStyle, PerRow } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
3
3
  /** One polygon per point, its Voronoi cell (svelteplot's `Voronoi`). */
4
4
  export type VoronoiMarkerConfig = {
5
5
  type: 'voronoi';
6
- styles?: AreaStyle;
6
+ styles?: PerRow<AreaStyle>;
7
7
  } & CommonMarkerConfigWithColor;
@@ -1,4 +1,5 @@
1
- import type { AreaStyle } from '../../plots/styling';
1
+ import type { AreaStyle, PerRow } from '../../plots/styling';
2
+ import type { CommonMarkerConfigWithLabel } from '../channels/commonMarkerConfigWithLabel';
2
3
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
3
4
  import type { CommonMarkerConfigWithInterval } from '../channels/commonMarkerConfigWithInterval';
4
5
  /** A waffle chart bar: the value as a grid of unit squares (svelteplot's `WaffleX`/`WaffleY`). */
@@ -9,5 +10,5 @@ export type WaffleMarkerConfig = {
9
10
  multiple?: number;
10
11
  gap?: number;
11
12
  round?: boolean;
12
- styles?: AreaStyle;
13
- } & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval;
13
+ styles?: PerRow<AreaStyle>;
14
+ } & CommonMarkerConfigWithColor & CommonMarkerConfigWithInterval & CommonMarkerConfigWithLabel;
@@ -1,4 +1,4 @@
1
- import type { DotStyle } from '../../plots/styling';
1
+ import type { DotStyle, PerRow } from '../../plots/styling';
2
2
  import type { CommonMarkerConfigWithColor } from '../channels/commonMarkerConfigWithColor';
3
3
  import type { CommonMarkerConfigWithRadius } from '../channels/commonMarkerConfigWithRadius';
4
4
  import type { CommonMarkerConfigWithRowOffset } from '../channels/commonMarkerConfigWithRowOffset';
@@ -6,5 +6,5 @@ import type { CommonMarkerConfigWithSymbol } from '../channels/commonMarkerConfi
6
6
  /** A point mark (svelteplot's `Dot`), usable on any plot kind. */
7
7
  export type DotMarkerConfig = CommonMarkerConfigWithRowOffset<{
8
8
  type: 'dot';
9
- styles?: DotStyle;
9
+ styles?: PerRow<DotStyle>;
10
10
  } & CommonMarkerConfigWithRadius & CommonMarkerConfigWithColor & CommonMarkerConfigWithSymbol>;