@internetstiftelsen/charts 0.9.2 → 0.10.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.
- package/README.md +136 -2
- package/dist/bar.d.ts +3 -1
- package/dist/bar.js +167 -327
- package/dist/base-chart.d.ts +16 -1
- package/dist/base-chart.js +89 -30
- package/dist/chart-group.d.ts +121 -0
- package/dist/chart-group.js +1097 -0
- package/dist/chart-interface.d.ts +1 -1
- package/dist/donut-chart.js +1 -1
- package/dist/gauge-chart.js +1 -1
- package/dist/legend-state.d.ts +19 -0
- package/dist/legend-state.js +81 -0
- package/dist/legend.d.ts +5 -2
- package/dist/legend.js +35 -29
- package/dist/pie-chart.js +1 -1
- package/dist/scatter.d.ts +16 -0
- package/dist/scatter.js +163 -0
- package/dist/tooltip.d.ts +2 -1
- package/dist/tooltip.js +3 -3
- package/dist/types.d.ts +16 -0
- package/dist/validation.d.ts +4 -0
- package/dist/validation.js +19 -0
- package/dist/xy-chart.d.ts +16 -1
- package/dist/xy-chart.js +317 -102
- package/docs/chart-group.md +213 -0
- package/docs/components.md +308 -0
- package/docs/donut-chart.md +193 -0
- package/docs/gauge-chart.md +175 -0
- package/docs/getting-started.md +311 -0
- package/docs/pie-chart.md +123 -0
- package/docs/theming.md +162 -0
- package/docs/word-cloud-chart.md +98 -0
- package/docs/xy-chart.md +502 -0
- package/package.json +2 -1
package/docs/xy-chart.md
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
# XYChart API
|
|
2
|
+
|
|
3
|
+
The main chart class for creating XY-coordinate charts (line, scatter, area, bar, or mixed).
|
|
4
|
+
|
|
5
|
+
## Constructor
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
new XYChart(config: XYChartConfig)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Config Options
|
|
12
|
+
|
|
13
|
+
| Option | Type | Default | Description |
|
|
14
|
+
| ------------- | ---------------------------------- | ---------------------------------------------------- | --------------------------------------------------------------------- |
|
|
15
|
+
| `data` | `DataItem[] \| GroupedDataGroup[]` | required | Flat rows or grouped nested rows |
|
|
16
|
+
| `width` | `number` | - | Explicit chart width in pixels |
|
|
17
|
+
| `height` | `number` | - | Explicit chart height in pixels |
|
|
18
|
+
| `theme` | `DeepPartial<ChartTheme>` | - | Theme customization |
|
|
19
|
+
| `scales` | `AxisScaleConfig` | - | Scale configuration |
|
|
20
|
+
| `orientation` | `'vertical' \| 'horizontal'` | `'vertical'` | Chart orientation. Horizontal mode currently supports bar-only charts |
|
|
21
|
+
| `responsive` | `ResponsiveConfig` | - | Container-query responsive overrides (theme + components) |
|
|
22
|
+
| `barStack` | `BarStackConfig` | `{ mode: 'normal', gap: 0.1, reverseSeries: false }` | Bar stacking configuration |
|
|
23
|
+
| `areaStack` | `AreaStackConfig` | `{ mode: 'none' }` | Area stacking configuration |
|
|
24
|
+
|
|
25
|
+
### Theme Options
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
theme: {
|
|
29
|
+
margins: { // Base margins around plot area
|
|
30
|
+
top: number, // default: 20
|
|
31
|
+
right: number, // default: 20
|
|
32
|
+
bottom: number, // default: 20
|
|
33
|
+
left: number, // default: 20
|
|
34
|
+
},
|
|
35
|
+
colorPalette: string[], // Colors for auto-assignment
|
|
36
|
+
grid: {
|
|
37
|
+
color: string, // Grid line color (default: '#e0e0e0')
|
|
38
|
+
opacity: number, // Grid line opacity (default: 0.5)
|
|
39
|
+
},
|
|
40
|
+
axis: {
|
|
41
|
+
fontFamily: string,
|
|
42
|
+
fontSize: string,
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use top-level `width` and `height` for fixed-size charts. If omitted, the chart
|
|
48
|
+
sizes itself from the render container.
|
|
49
|
+
|
|
50
|
+
### Grouped Dataset Shape
|
|
51
|
+
|
|
52
|
+
Grouped categorical datasets can be passed as nested groups:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
[
|
|
56
|
+
{
|
|
57
|
+
"group": "Internetanv. 8+ år",
|
|
58
|
+
"data": [
|
|
59
|
+
{
|
|
60
|
+
"Kategori": "Man",
|
|
61
|
+
"Använt sociala medier varje dag": "83%",
|
|
62
|
+
"Använt sociala medier minst varje vecka": "90%"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"Kategori": "Kvinna",
|
|
66
|
+
"Använt sociala medier varje dag": "86%",
|
|
67
|
+
"Använt sociala medier minst varje vecka": "92%"
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Rules for grouped datasets:
|
|
75
|
+
|
|
76
|
+
- The first key of each row object is used as the category key (for example `Kategori`).
|
|
77
|
+
- Remaining keys are treated as metric columns.
|
|
78
|
+
- Each `group` must be a non-empty string.
|
|
79
|
+
- Group labels are rendered on a second x-axis row when `XAxis.showGroupLabels` is enabled.
|
|
80
|
+
- CSV/XLSX exports use spreadsheet-style grouped rows (blank first two headers, blank continuation group cells, no spacer rows).
|
|
81
|
+
|
|
82
|
+
### Scale Options
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
scales: {
|
|
86
|
+
x: {
|
|
87
|
+
type: 'band' | 'linear' | 'time' | 'log',
|
|
88
|
+
domain?: ScaleDomainValue[],
|
|
89
|
+
padding?: number,
|
|
90
|
+
groupGap?: number, // adds visual slot gaps between grouped categories
|
|
91
|
+
reverse?: boolean, // reverse the rendered axis direction
|
|
92
|
+
nice?: boolean,
|
|
93
|
+
},
|
|
94
|
+
y: {
|
|
95
|
+
type: 'band' | 'linear' | 'time' | 'log',
|
|
96
|
+
domain?: ScaleDomainValue[],
|
|
97
|
+
padding?: number,
|
|
98
|
+
reverse?: boolean, // reverse the rendered axis direction
|
|
99
|
+
nice?: boolean,
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Categorical `y` axes render in data order from top to bottom by default. Set
|
|
105
|
+
`reverse: true` on either axis to intentionally flip its direction for category,
|
|
106
|
+
numeric, time, or log scales.
|
|
107
|
+
|
|
108
|
+
## Scale Types
|
|
109
|
+
|
|
110
|
+
`XYChart` supports categorical, numeric, temporal, and logarithmic axes.
|
|
111
|
+
|
|
112
|
+
### Time Scale
|
|
113
|
+
|
|
114
|
+
Use `time` when the axis values are `Date` objects:
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
const chart = new XYChart({
|
|
118
|
+
data: [
|
|
119
|
+
{ date: new Date('2024-01-01'), value: 100 },
|
|
120
|
+
{ date: new Date('2024-01-02'), value: 150 },
|
|
121
|
+
{ date: new Date('2024-01-03'), value: 120 },
|
|
122
|
+
],
|
|
123
|
+
scales: {
|
|
124
|
+
x: { type: 'time', nice: true },
|
|
125
|
+
y: { type: 'linear', nice: true },
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Logarithmic Scale
|
|
131
|
+
|
|
132
|
+
Use `log` for exponential data. Log scales require positive values and a
|
|
133
|
+
strictly positive domain:
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
const chart = new XYChart({
|
|
137
|
+
data: [
|
|
138
|
+
{ x: 1, y: 10 },
|
|
139
|
+
{ x: 2, y: 100 },
|
|
140
|
+
{ x: 3, y: 1000 },
|
|
141
|
+
{ x: 4, y: 10000 },
|
|
142
|
+
],
|
|
143
|
+
scales: {
|
|
144
|
+
y: { type: 'log', domain: [1, 10000] },
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Bar series cannot use logarithmic value axes because bars always render from a
|
|
150
|
+
zero baseline.
|
|
151
|
+
|
|
152
|
+
### Custom Domains
|
|
153
|
+
|
|
154
|
+
Set `domain` to override the automatic extent calculation:
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
const chart = new XYChart({
|
|
158
|
+
data,
|
|
159
|
+
scales: {
|
|
160
|
+
y: {
|
|
161
|
+
type: 'linear',
|
|
162
|
+
domain: [0, 100],
|
|
163
|
+
nice: true,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
For bar charts, automatic numeric value domains always include `0`. If you set
|
|
170
|
+
an explicit numeric domain or `min`/`max` for the bar value axis, that final
|
|
171
|
+
domain must still include `0`.
|
|
172
|
+
|
|
173
|
+
On horizontal bar charts, category order is controlled with `scales.x.reverse`
|
|
174
|
+
because `x` remains the categorical dimension even when it renders vertically.
|
|
175
|
+
|
|
176
|
+
## Responsive Overrides
|
|
177
|
+
|
|
178
|
+
Use chart-level `responsive` to declare breakpoint-specific theme and component
|
|
179
|
+
overrides before layout is calculated:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
const chart = new XYChart({
|
|
183
|
+
data,
|
|
184
|
+
responsive: {
|
|
185
|
+
breakpoints: {
|
|
186
|
+
sm: {
|
|
187
|
+
maxWidth: 640,
|
|
188
|
+
theme: {
|
|
189
|
+
axis: {
|
|
190
|
+
fontSize: 11,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
components: [
|
|
194
|
+
{
|
|
195
|
+
match: { type: 'xAxis' },
|
|
196
|
+
override: {
|
|
197
|
+
display: false,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
},
|
|
202
|
+
md: {
|
|
203
|
+
minWidth: 641,
|
|
204
|
+
maxWidth: 768,
|
|
205
|
+
theme: {
|
|
206
|
+
axis: {
|
|
207
|
+
fontSize: 12,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
`minWidth` and `maxWidth` are both optional, but breakpoints that omit both are
|
|
217
|
+
ignored. Multiple breakpoints can match at the same width; matching breakpoints
|
|
218
|
+
merge in declaration order, so later entries win when they override the same
|
|
219
|
+
values.
|
|
220
|
+
|
|
221
|
+
If you need dynamic logic, `responsive.beforeRender` still runs before spacing
|
|
222
|
+
is measured after declarative breakpoint overrides are merged. It receives
|
|
223
|
+
`context.activeBreakpoints` with every match and `context.breakpoint` as the
|
|
224
|
+
last matching breakpoint name.
|
|
225
|
+
|
|
226
|
+
## Validation
|
|
227
|
+
|
|
228
|
+
`XYChart` validates configuration and series data early:
|
|
229
|
+
|
|
230
|
+
- `data` must be a non-empty array.
|
|
231
|
+
- Series `dataKey` values must exist in the dataset.
|
|
232
|
+
- Rendered series values must resolve to numeric values.
|
|
233
|
+
- Log scales reject zero or negative domain values and zero or negative series values.
|
|
234
|
+
- Bar series require a linear value axis and explicit numeric bar domains must include `0`.
|
|
235
|
+
|
|
236
|
+
## Methods
|
|
237
|
+
|
|
238
|
+
### addChild(component)
|
|
239
|
+
|
|
240
|
+
Adds a component to the chart. Returns `this` for chaining.
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
chart
|
|
244
|
+
.addChild(new XAxis({ dataKey: 'date' }))
|
|
245
|
+
.addChild(new YAxis())
|
|
246
|
+
.addChild(new Line({ dataKey: 'value' }));
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### render(target)
|
|
250
|
+
|
|
251
|
+
Renders the chart to a DOM element. Accepts a CSS selector or HTMLElement. Automatically sets up resize handling.
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
chart.render('#chart-container');
|
|
255
|
+
// or
|
|
256
|
+
chart.render(document.getElementById('chart-container'));
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### update(data)
|
|
260
|
+
|
|
261
|
+
Updates the chart with new data and re-renders.
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
chart.update(newData);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### destroy()
|
|
268
|
+
|
|
269
|
+
Cleans up all resources, removes resize observer, and clears the chart from the DOM.
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
chart.destroy();
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Line
|
|
278
|
+
|
|
279
|
+
Renders a line series on the chart.
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
new Line({
|
|
283
|
+
dataKey: string, // Key in data objects for Y values (required)
|
|
284
|
+
stroke?: string, // Line color (auto-assigned if omitted)
|
|
285
|
+
strokeWidth?: number, // Line width in pixels (default: 2)
|
|
286
|
+
})
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Example
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
// Auto-assigned colors
|
|
293
|
+
chart.addChild(new Line({ dataKey: 'revenue' }));
|
|
294
|
+
chart.addChild(new Line({ dataKey: 'expenses' }));
|
|
295
|
+
|
|
296
|
+
// Manual colors
|
|
297
|
+
chart.addChild(new Line({ dataKey: 'revenue', stroke: '#00ff00' }));
|
|
298
|
+
chart.addChild(new Line({ dataKey: 'expenses', stroke: '#ff0000' }));
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Scatter
|
|
304
|
+
|
|
305
|
+
Renders a point-only scatter series on the chart.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
new Scatter({
|
|
309
|
+
dataKey: string, // Key in data objects for Y values (required)
|
|
310
|
+
stroke?: string, // Point color (auto-assigned if omitted)
|
|
311
|
+
pointSize?: number, // Point radius in pixels (default: theme.line.point.size)
|
|
312
|
+
valueLabel?: { show?: boolean } // Point value badges
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Example
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
chart.addChild(new Scatter({ dataKey: 'revenue' }));
|
|
320
|
+
chart.addChild(new Scatter({ dataKey: 'expenses', pointSize: 7 }));
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Bar
|
|
326
|
+
|
|
327
|
+
Renders a bar series on the chart.
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
new Bar({
|
|
331
|
+
dataKey: string, // Key in data objects for values (required)
|
|
332
|
+
fill?: string, // Bar color (auto-assigned if omitted)
|
|
333
|
+
maxBarSize?: number, // Max width/height depending on chart orientation
|
|
334
|
+
side?: 'left' | 'right', // Mirror horizontal bars to the left without changing source data
|
|
335
|
+
valueLabel?: {
|
|
336
|
+
show?: boolean,
|
|
337
|
+
position?: 'inside' | 'outside',
|
|
338
|
+
insidePosition?: 'top' | 'middle' | 'bottom'
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Example
|
|
344
|
+
|
|
345
|
+
```javascript
|
|
346
|
+
chart.addChild(new Bar({ dataKey: 'sales' }));
|
|
347
|
+
chart.addChild(new Bar({ dataKey: 'returns', fill: '#ff6b6b' }));
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Use `XYChart.orientation: 'horizontal'` for horizontal bar charts:
|
|
351
|
+
|
|
352
|
+
```javascript
|
|
353
|
+
const chart = new XYChart({
|
|
354
|
+
data,
|
|
355
|
+
orientation: 'horizontal',
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
chart
|
|
359
|
+
.addChild(new XAxis({ dataKey: 'metric' }))
|
|
360
|
+
.addChild(new YAxis())
|
|
361
|
+
.addChild(new Bar({ dataKey: 'current' }))
|
|
362
|
+
.addChild(new Bar({ dataKey: 'benchmark' }));
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Horizontal and vertical bar charts now render from a true zero baseline. When a
|
|
366
|
+
bar dataset contains both positive and negative values, bars automatically
|
|
367
|
+
diverge around `0`.
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
const chart = new XYChart({
|
|
371
|
+
data: [
|
|
372
|
+
{ metric: 'Pricing', delta: -18 },
|
|
373
|
+
{ metric: 'Feature set', delta: 24 },
|
|
374
|
+
{ metric: 'Support', delta: 11 },
|
|
375
|
+
],
|
|
376
|
+
orientation: 'horizontal',
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
chart
|
|
380
|
+
.addChild(new XAxis({ dataKey: 'metric' }))
|
|
381
|
+
.addChild(new YAxis())
|
|
382
|
+
.addChild(new Bar({ dataKey: 'delta' }));
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Population-pyramid style charts can keep both series positive in source data and
|
|
386
|
+
mirror one series to the left at render time:
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
const chart = new XYChart({
|
|
390
|
+
data: [
|
|
391
|
+
{
|
|
392
|
+
source: 'Digitala tidningar/nyhetssajter',
|
|
393
|
+
yngre: '51%',
|
|
394
|
+
äldre: '19%',
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
source: 'Tv-kanal (SVT, TV4 etc.)',
|
|
398
|
+
yngre: '45%',
|
|
399
|
+
äldre: '86%',
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
orientation: 'horizontal',
|
|
403
|
+
scales: {
|
|
404
|
+
y: { type: 'linear', min: -100, max: 100, nice: false },
|
|
405
|
+
},
|
|
406
|
+
barStack: { mode: 'normal' },
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
chart
|
|
410
|
+
.addChild(
|
|
411
|
+
new XAxis({
|
|
412
|
+
dataKey: 'source',
|
|
413
|
+
tickFormat: (value) => `${Math.abs(Number(value))}%`,
|
|
414
|
+
}),
|
|
415
|
+
)
|
|
416
|
+
.addChild(new YAxis())
|
|
417
|
+
.addChild(new Bar({ dataKey: 'yngre', side: 'left' }))
|
|
418
|
+
.addChild(new Bar({ dataKey: 'äldre' }));
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
Horizontal orientation currently supports bar-only charts. Mixed horizontal
|
|
422
|
+
bar/line, bar/scatter, or bar/area charts are rejected.
|
|
423
|
+
|
|
424
|
+
### Stacking Modes
|
|
425
|
+
|
|
426
|
+
Bar charts support different stacking modes:
|
|
427
|
+
|
|
428
|
+
- `none` - Bars side by side (default)
|
|
429
|
+
- `normal` - Stacked bars
|
|
430
|
+
- `percent` - 100% stacked bars
|
|
431
|
+
- `layer` - Overlapping bars
|
|
432
|
+
|
|
433
|
+
Use `barStack.reverseSeries: true` to reverse bar series display order for rendering, legend entries, and tooltip rows without changing data exports.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Area
|
|
438
|
+
|
|
439
|
+
Renders an area series on the chart.
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
new Area({
|
|
443
|
+
dataKey: string, // Key in data objects for Y values (required)
|
|
444
|
+
fill?: string, // Area fill color (auto-assigned if omitted)
|
|
445
|
+
stroke?: string, // Optional line color (defaults to fill color)
|
|
446
|
+
opacity?: number, // Fill opacity (default: 0.3)
|
|
447
|
+
curve?: 'linear' | 'monotone' | 'step' | 'natural' | 'basis' | 'cardinal',
|
|
448
|
+
stackId?: string | number, // Group key used for area stacking
|
|
449
|
+
baseline?: number, // Baseline for non-stacked area (default: 0)
|
|
450
|
+
showLine?: boolean, // Show top stroke line (default: true)
|
|
451
|
+
showPoints?: boolean, // Show points on top line (default: false)
|
|
452
|
+
valueLabel?: { show?: boolean } // Point value badges
|
|
453
|
+
})
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Example
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
chart.addChild(new Area({ dataKey: 'revenue' }));
|
|
460
|
+
chart.addChild(
|
|
461
|
+
new Area({
|
|
462
|
+
dataKey: 'expenses',
|
|
463
|
+
fill: '#ff6b6b',
|
|
464
|
+
opacity: 0.2,
|
|
465
|
+
curve: 'monotone',
|
|
466
|
+
showPoints: true,
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Area Stacking
|
|
472
|
+
|
|
473
|
+
Area charts support stacking when series share the same `stackId`:
|
|
474
|
+
|
|
475
|
+
- `none` - No area stacking (default)
|
|
476
|
+
- `normal` - Absolute stacking
|
|
477
|
+
- `percent` - Normalized 100% stacking
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
const chart = new XYChart({
|
|
481
|
+
data,
|
|
482
|
+
areaStack: { mode: 'percent' },
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
chart.addChild(new Area({ dataKey: 'desktop', stackId: 'traffic' })).addChild(new Area({ dataKey: 'mobile', stackId: 'traffic' }));
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## Mixed Charts
|
|
491
|
+
|
|
492
|
+
Combine lines, scatter series, areas, and bars in the same chart:
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
const chart = new XYChart({ data });
|
|
496
|
+
|
|
497
|
+
chart
|
|
498
|
+
.addChild(new Bar({ dataKey: 'volume' }))
|
|
499
|
+
.addChild(new Scatter({ dataKey: 'orders' }))
|
|
500
|
+
.addChild(new Area({ dataKey: 'averageRange', opacity: 0.2 }))
|
|
501
|
+
.addChild(new Line({ dataKey: 'price' }));
|
|
502
|
+
```
|
package/package.json
CHANGED