@internetstiftelsen/charts 0.12.0 → 0.13.1

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.
package/dist/types.d.ts CHANGED
@@ -69,6 +69,9 @@ export type ChartTheme = {
69
69
  itemSpacingX: number;
70
70
  itemSpacingY: number;
71
71
  };
72
+ text: {
73
+ variants: Record<string, TextVariantStyle>;
74
+ };
72
75
  tooltip: {
73
76
  background: string;
74
77
  border: string;
@@ -181,16 +184,25 @@ export type ValueLabelConfig = {
181
184
  export type LineValueLabelConfig = ValueLabelConfig & {
182
185
  show?: boolean;
183
186
  };
187
+ export type LinePointVisibility = 'always' | 'hover' | 'never';
188
+ export type LinePointsConfig = {
189
+ show?: LinePointVisibility;
190
+ };
184
191
  export type BarValueLabelConfig = ValueLabelConfig & {
185
192
  show?: boolean;
186
193
  position?: 'inside' | 'outside';
187
194
  insidePosition?: 'top' | 'middle' | 'bottom';
188
195
  };
189
196
  export type BarSide = 'left' | 'right';
197
+ export type CurveType = 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal';
198
+ export type LineCurveType = CurveType;
199
+ export type AreaCurveType = CurveType;
190
200
  export type LineConfigBase = {
191
201
  dataKey: string;
192
202
  stroke?: string;
193
203
  strokeWidth?: number;
204
+ curve?: LineCurveType;
205
+ points?: LinePointsConfig;
194
206
  valueLabel?: LineValueLabelConfig;
195
207
  };
196
208
  export type LineConfig = LineConfigBase & {
@@ -216,7 +228,6 @@ export type BarConfigBase = {
216
228
  export type BarConfig = BarConfigBase & {
217
229
  exportHooks?: ExportHooks<BarConfigBase>;
218
230
  };
219
- export type AreaCurveType = 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal';
220
231
  export type AreaConfigBase = {
221
232
  dataKey: string;
222
233
  fill?: string;
@@ -333,13 +344,43 @@ export type LegendItem = {
333
344
  color: string;
334
345
  visible: boolean;
335
346
  };
347
+ export type TextPosition = 'top' | 'bottom';
348
+ export type TextAlign = 'left' | 'center' | 'right';
349
+ export type TextVariantStyle = {
350
+ fontSize?: number;
351
+ fontWeight?: string;
352
+ fontFamily?: string;
353
+ color?: string;
354
+ lineHeight?: number;
355
+ marginTop?: number;
356
+ marginBottom?: number;
357
+ };
358
+ export type TextConfigBase = {
359
+ display?: boolean;
360
+ text: string;
361
+ position?: TextPosition;
362
+ variant?: string;
363
+ align?: TextAlign;
364
+ fontSize?: number;
365
+ fontWeight?: string;
366
+ fontFamily?: string;
367
+ color?: string;
368
+ lineHeight?: number;
369
+ marginTop?: number;
370
+ marginBottom?: number;
371
+ };
372
+ export type TextConfig = TextConfigBase & {
373
+ exportHooks?: ExportHooks<TextConfigBase>;
374
+ };
336
375
  export type TitleConfigBase = {
337
376
  display?: boolean;
338
377
  text: string;
339
378
  fontSize?: number;
340
379
  fontWeight?: string;
341
380
  fontFamily?: string;
342
- align?: 'left' | 'center' | 'right';
381
+ align?: TextAlign;
382
+ color?: string;
383
+ lineHeight?: number;
343
384
  marginTop?: number;
344
385
  marginBottom?: number;
345
386
  };
@@ -18,7 +18,7 @@ new ChartGroup(config: ChartGroupConfig)
18
18
  | `syncY` | `boolean` | `false` | Sync the Y domain across visible vertical `XYChart` children |
19
19
  | `height` | `number` | container height | Fixed total group height. Omit it to size from the container |
20
20
  | `chartHeight` | `number` | `DEFAULT_CHART_HEIGHT` | Fallback child height when neither the child nor container provides one |
21
- | `theme` | `DeepPartial<ChartTheme>` | - | Theme override for the shared group legend and title |
21
+ | `theme` | `DeepPartial<ChartTheme>` | - | Theme override for the shared group legend and text |
22
22
  | `responsive` | `ChartGroupResponsiveConfig` | - | Declarative responsive overrides for group-level `cols` and `gap` |
23
23
 
24
24
  `ChartGroup` manages child widths. If a child chart has an explicit `width`,
@@ -32,6 +32,7 @@ import { XYChart } from '@internetstiftelsen/charts/xy-chart';
32
32
  import { Line } from '@internetstiftelsen/charts/line';
33
33
  import { Bar } from '@internetstiftelsen/charts/bar';
34
34
  import { Legend } from '@internetstiftelsen/charts/legend';
35
+ import { Text } from '@internetstiftelsen/charts/text';
35
36
  import { Title } from '@internetstiftelsen/charts/title';
36
37
 
37
38
  const lineChart = new XYChart({ data: lineData });
@@ -53,6 +54,13 @@ const group = new ChartGroup({
53
54
 
54
55
  group
55
56
  .addChild(new Title({ text: 'Revenue vs Expenses' }))
57
+ .addChild(
58
+ new Text({
59
+ text: 'Source: finance team',
60
+ position: 'bottom',
61
+ variant: 'caption',
62
+ }),
63
+ )
56
64
  .addChart(barChart, { span: 1 })
57
65
  .addChart(lineChart, { span: 2 })
58
66
  .addChild(new Legend());
@@ -165,13 +173,21 @@ After a breakpoint's `maxWidth`, that breakpoint stops matching. Use the base
165
173
  group config plus `minWidth` breakpoints for mobile-first layouts, or the base
166
174
  group config plus `maxWidth` breakpoints for desktop-down layouts.
167
175
 
168
- ## Title
176
+ ## Text and Title
169
177
 
170
- `ChartGroup` accepts `Title` via `addChild()` and renders it above the grouped
171
- chart layout:
178
+ `ChartGroup` accepts `Text` and `Title` via `addChild()`. Top text renders above
179
+ the grouped chart layout. Bottom text renders below the grouped chart layout and
180
+ shared legend:
172
181
 
173
182
  ```typescript
174
183
  group.addChild(new Title({ text: 'Revenue vs Expenses' }));
184
+ group.addChild(
185
+ new Text({
186
+ text: 'Source: finance team',
187
+ position: 'bottom',
188
+ variant: 'caption',
189
+ }),
190
+ );
175
191
  ```
176
192
 
177
193
  ## Legend
@@ -208,6 +224,9 @@ await group.export('pdf');
208
224
 
209
225
  - Export width can be overridden with `options.width`
210
226
  - Export height is layout-derived in v1 and cannot be overridden
211
- - Group titles are included in the combined export
227
+ - Group text is included in the combined export
228
+ - Group-level `Text` and `Title` export hooks run during visual export, so text
229
+ can be hidden live with `display: false` and included only in export by
230
+ returning `{ display: true }` from `beforeRender`
212
231
  - Child chart legends are suppressed in the combined export
213
232
  - Non-visual exports (`json`, `csv`, `xlsx`) are not supported in v1
@@ -224,34 +224,116 @@ charts from one shared legend.
224
224
 
225
225
  ---
226
226
 
227
- ## Title
227
+ ## Text
228
228
 
229
- Renders a title for the chart.
229
+ Renders layout-aware text above or below the chart. Use it for titles,
230
+ subtitles, captions, source notes, and other short chart copy.
230
231
 
231
232
  ```typescript
232
- new Title({
233
- display?: boolean, // Render title and reserve layout space (default: true)
234
- text: string, // Title text (required)
235
- fontSize?: number, // Font size in pixels (default: 18)
236
- fontWeight?: string, // Font weight (default: 'bold')
237
- align?: 'left' | 'center' | 'right', // Alignment (default: 'center')
238
- marginTop?: number, // Space above title (default: 10)
239
- marginBottom?: number, // Space below title (default: 15)
233
+ new Text({
234
+ display?: boolean, // Render text and reserve layout space (default: true)
235
+ text: string, // Text content (required)
236
+ position?: 'top' | 'bottom', // Layout position (default: 'top')
237
+ variant?: string, // Theme variant (default: 'caption')
238
+ align?: 'left' | 'center' | 'right', // Alignment (default: 'center')
239
+ fontSize?: number, // Override variant font size
240
+ fontWeight?: string, // Override variant font weight
241
+ fontFamily?: string, // Override variant font family
242
+ color?: string, // Override variant text color
243
+ lineHeight?: number, // Override variant line height
244
+ marginTop?: number, // Override variant top spacing
245
+ marginBottom?: number, // Override variant bottom spacing
240
246
  })
241
247
  ```
242
248
 
243
249
  ### Example
244
250
 
245
251
  ```javascript
252
+ import { Text } from '@internetstiftelsen/charts/text';
253
+
254
+ chart
255
+ .addChild(
256
+ new Text({
257
+ text: 'Monthly Revenue',
258
+ variant: 'title',
259
+ align: 'left',
260
+ }),
261
+ )
262
+ .addChild(
263
+ new Text({
264
+ text: 'Revenue by month, SEK',
265
+ variant: 'subtitle',
266
+ align: 'left',
267
+ }),
268
+ )
269
+ .addChild(
270
+ new Text({
271
+ text: 'Source: Internal reporting',
272
+ position: 'bottom',
273
+ variant: 'caption',
274
+ align: 'left',
275
+ }),
276
+ );
277
+ ```
278
+
279
+ Text variants come from `theme.text.variants`. Built-in variants are `title`,
280
+ `subtitle`, and `caption`. Component config overrides the selected variant.
281
+
282
+ ```javascript
283
+ const chart = new XYChart({
284
+ data,
285
+ theme: {
286
+ text: {
287
+ variants: {
288
+ source: {
289
+ fontSize: 10,
290
+ color: '#64748b',
291
+ marginTop: 6,
292
+ marginBottom: 0,
293
+ },
294
+ },
295
+ },
296
+ },
297
+ });
298
+
246
299
  chart.addChild(
247
- new Title({
248
- text: 'Monthly Revenue',
249
- align: 'left',
250
- fontSize: 20,
300
+ new Text({
301
+ text: 'Source: Internetstiftelsen',
302
+ position: 'bottom',
303
+ variant: 'source',
251
304
  }),
252
305
  );
253
306
  ```
254
307
 
308
+ ## Title
309
+
310
+ `Title` remains available as a compatibility shortcut for top title text:
311
+
312
+ ```typescript
313
+ new Title({
314
+ display?: boolean,
315
+ text: string,
316
+ fontSize?: number,
317
+ fontWeight?: string,
318
+ fontFamily?: string,
319
+ align?: 'left' | 'center' | 'right',
320
+ color?: string,
321
+ lineHeight?: number,
322
+ marginTop?: number,
323
+ marginBottom?: number,
324
+ })
325
+ ```
326
+
327
+ It maps to the same rendering and layout behavior as:
328
+
329
+ ```javascript
330
+ new Text({
331
+ text: 'Monthly Revenue',
332
+ position: 'top',
333
+ variant: 'title',
334
+ });
335
+ ```
336
+
255
337
  ---
256
338
 
257
339
  ## Export Hooks
@@ -346,12 +428,14 @@ Components are rendered in the order they're added. A typical order:
346
428
 
347
429
  ```javascript
348
430
  chart
349
- .addChild(new Title({ text: 'Chart Title' }))
431
+ .addChild(new Text({ text: 'Chart Title', variant: 'title' }))
432
+ .addChild(new Text({ text: 'Subtitle', variant: 'subtitle' }))
350
433
  .addChild(new Grid({ value: true }))
351
434
  .addChild(new XAxis({ dataKey: 'date' }))
352
435
  .addChild(new YAxis())
353
436
  .addChild(new Tooltip())
354
437
  .addChild(new Legend({ position: 'bottom' }))
438
+ .addChild(new Text({ text: 'Source note', position: 'bottom' }))
355
439
  .addChild(new Line({ dataKey: 'value1' }))
356
440
  .addChild(new Line({ dataKey: 'value2' }));
357
441
  ```
@@ -176,7 +176,8 @@ new DonutCenterContent({
176
176
  DonutChart supports the following components via `addChild()`:
177
177
 
178
178
  - `DonutCenterContent` - Center text content
179
- - `Title` - Chart title
179
+ - `Text` - Chart text, captions, and source notes
180
+ - `Title` - Shortcut for top title text
180
181
  - `Legend` - Interactive legend (click to toggle segments)
181
182
  - `Tooltip` - Hover tooltips with segment info
182
183
 
@@ -170,6 +170,7 @@ const chart = new GaugeChart({
170
170
 
171
171
  GaugeChart supports the following components via `addChild()`:
172
172
 
173
- - `Title` - Chart title
173
+ - `Text` - Chart text, captions, and source notes
174
+ - `Title` - Shortcut for top title text
174
175
  - `Tooltip` - Hover tooltip (value, target)
175
176
  - `Legend` - Segment legend with visibility toggles
@@ -366,5 +366,5 @@ directly when laying out and rendering the cloud.
366
366
  - [DonutChart API](./donut-chart.md) - Donut/pie charts
367
367
  - [PieChart API](./pie-chart.md) - Pie charts
368
368
  - [GaugeChart API](./gauge-chart.md) - Gauge charts
369
- - [Components](./components.md) - Axes, Grid, Tooltip, Legend, Title
369
+ - [Components](./components.md) - Axes, Grid, Tooltip, Legend, Text, Title
370
370
  - [Theming](./theming.md) - Customize colors and styles
package/docs/pie-chart.md CHANGED
@@ -108,7 +108,8 @@ fit inside its slice is hidden. In `auto` mode, labels that are too tight (based
108
108
 
109
109
  PieChart supports the following components via `addChild()`:
110
110
 
111
- - `Title` - Chart title
111
+ - `Text` - Chart text, captions, and source notes
112
+ - `Title` - Shortcut for top title text
112
113
  - `Legend` - Interactive legend (click to toggle slices)
113
114
  - `Tooltip` - Hover/focus tooltips with slice info
114
115
 
package/docs/theming.md CHANGED
@@ -111,6 +111,41 @@ const data = [
111
111
 
112
112
  ---
113
113
 
114
+ ## Text Variants
115
+
116
+ `Text` uses `theme.text.variants` for reusable typography and spacing. Built-in
117
+ variants are `title`, `subtitle`, and `caption`; add custom keys when a chart
118
+ needs another text style.
119
+
120
+ ```javascript
121
+ theme: {
122
+ text: {
123
+ variants: {
124
+ title: {
125
+ fontSize: 18,
126
+ fontWeight: 'bold',
127
+ color: '#1f2a36',
128
+ lineHeight: 1.2,
129
+ marginTop: 10,
130
+ marginBottom: 15,
131
+ },
132
+ source: {
133
+ fontSize: 10,
134
+ color: '#64748b',
135
+ lineHeight: 1.3,
136
+ marginTop: 6,
137
+ marginBottom: 0,
138
+ },
139
+ },
140
+ },
141
+ }
142
+ ```
143
+
144
+ Component config overrides the chosen variant, so a one-off chart can adjust
145
+ `fontSize`, `color`, or spacing without changing the theme.
146
+
147
+ ---
148
+
114
149
  ## Donut Theme Defaults
115
150
 
116
151
  DonutChart has additional theme defaults:
@@ -82,6 +82,7 @@ chart.render('#word-cloud');
82
82
 
83
83
  ## Supported Components
84
84
 
85
+ - `Text`
85
86
  - `Title`
86
87
 
87
88
  `XAxis`, `YAxis`, `Grid`, `Legend`, and `Tooltip` are not used by
package/docs/xy-chart.md CHANGED
@@ -338,6 +338,10 @@ new Line({
338
338
  dataKey: string, // Key in data objects for Y values (required)
339
339
  stroke?: string, // Line color (auto-assigned if omitted)
340
340
  strokeWidth?: number, // Line width in pixels (default: 2)
341
+ curve?: 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal',
342
+ points?: {
343
+ show?: 'always' | 'hover' | 'never'
344
+ }, // Data point visibility (default: 'always')
341
345
  valueLabel?: {
342
346
  show?: boolean,
343
347
  formatter?: (dataKey, value, data) => string
@@ -355,8 +359,20 @@ chart.addChild(new Line({ dataKey: 'expenses' }));
355
359
  // Manual colors
356
360
  chart.addChild(new Line({ dataKey: 'revenue', stroke: '#00ff00' }));
357
361
  chart.addChild(new Line({ dataKey: 'expenses', stroke: '#ff0000' }));
362
+
363
+ // Smooth line interpolation
364
+ chart.addChild(new Line({ dataKey: 'revenue', curve: 'monotone' }));
365
+
366
+ // Show point circles only while hovering or focusing a tooltip target
367
+ chart
368
+ .addChild(new Line({ dataKey: 'revenue', points: { show: 'hover' } }))
369
+ .addChild(new Tooltip());
358
370
  ```
359
371
 
372
+ `points.show: 'hover'` uses `Tooltip` focus markers, so add a `Tooltip`
373
+ component when hover-only points should be visible. Use `'never'` to suppress
374
+ both static line points and tooltip focus markers for that line.
375
+
360
376
  ---
361
377
 
362
378
  ## Scatter
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.12.0",
2
+ "version": "0.13.1",
3
3
  "name": "@internetstiftelsen/charts",
4
4
  "type": "module",
5
5
  "sideEffects": false,