apexcharts-skill 2.2.0 → 3.1.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/.cursorrules +57 -19
- package/README.md +14 -10
- package/SKILL.md +165 -66
- package/index.js +1 -1
- package/package.json +1 -1
- package/references/bar-charts.md +130 -5
- package/references/cartesian-charts.md +96 -1
- package/references/circular-charts.md +52 -1
- package/references/{v6-features.md → feature-platform.md} +233 -30
- package/references/financial-charts.md +68 -0
- package/references/framework-wrappers.md +1 -1
- package/references/grid-charts.md +91 -1
- package/references/ssr.md +18 -9
- package/references/tree-shaking.md +119 -28
package/references/bar-charts.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
- **Range Bar** (`'rangeBar'`) — Bars with start/end values (used for timelines, Gantt charts)
|
|
8
8
|
- **Funnel** (`'funnel'`, **new in v6**): Stage-by-stage drop-off chart
|
|
9
9
|
- **Pyramid** (`'pyramid'`, **new in v6**): A funnel with the wide base at the bottom
|
|
10
|
+
- **Waterfall** (`'waterfall'`, **new in v7.1**): Deltas that accumulate into a running total
|
|
11
|
+
- **Dumbbell** (`'dumbbell'`, **new in v7.1**): Two or more measures per category, joined by a connector
|
|
10
12
|
|
|
11
13
|
## Tree-Shakeable Import
|
|
12
14
|
|
|
@@ -14,10 +16,16 @@
|
|
|
14
16
|
import ApexCharts from 'apexcharts/bar'
|
|
15
17
|
// Registers: bar, column, rangeBar
|
|
16
18
|
// Aliases: apexcharts/column, apexcharts/rangeBar
|
|
17
|
-
// Also covers funnel + pyramid (they normalize to the bar engine
|
|
19
|
+
// Also covers funnel + pyramid (they normalize to the bar engine)
|
|
20
|
+
|
|
21
|
+
// waterfall and dumbbell (v7.1) each add a feature module on top of the bar engine:
|
|
22
|
+
import ApexCharts from 'apexcharts/waterfall' // == apexcharts/bar + features/waterfall
|
|
23
|
+
import ApexCharts from 'apexcharts/dumbbell' // == apexcharts/bar + features/dumbbell
|
|
18
24
|
```
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
Both are **Tier 1**, so the default `apexcharts` bundle already has them and no import is needed there.
|
|
27
|
+
|
|
28
|
+
**Alias note:** `funnel` and `pyramid` are first-class `chart.type` aliases that render through the bar engine. Use them directly as `chart.type`; you do **not** need `plotOptions.bar.isFunnel`. `plotOptions.funnel` carries the funnel-specific shape options.
|
|
21
29
|
|
|
22
30
|
**Histogram (v6.9):** `chart.type: 'histogram'` also renders through the bar pathway, but its series carry raw observations that the chart bins itself, and the binning needs the stats feature (`apexcharts/histogram` entry, or `apexcharts/features/stats` alongside `apexcharts/bar`). It is documented with the other statistical charts in `references/financial-charts.md`.
|
|
23
31
|
|
|
@@ -184,6 +192,105 @@ Same shape as funnel, but order values **smallest → largest** so the wide base
|
|
|
184
192
|
}
|
|
185
193
|
```
|
|
186
194
|
|
|
195
|
+
### Waterfall (v7.1)
|
|
196
|
+
|
|
197
|
+
`chart.type: 'waterfall'` **accumulates the running total for you**. The series holds the **deltas**; a row flagged `isSubtotal` or `isTotal` draws the running total from zero at that position and carries **no `y` of its own**. Connectors bridge each bar's finish to the next one's start, and rising, falling and total bars take their own colors.
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
{
|
|
201
|
+
chart: { type: 'waterfall', height: 350 },
|
|
202
|
+
series: [{
|
|
203
|
+
name: 'Operating income',
|
|
204
|
+
data: [
|
|
205
|
+
{ x: 'Net revenue', y: 8786000 },
|
|
206
|
+
{ x: 'Cost of sales', y: -2786000 },
|
|
207
|
+
{ x: 'Gross profit', isSubtotal: true }, // no y: measured for you
|
|
208
|
+
{ x: 'Operating expenses', y: -1786000 },
|
|
209
|
+
{ x: 'Operating income', isTotal: true }, // no y: sum from zero
|
|
210
|
+
],
|
|
211
|
+
}],
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Row shape** (`ApexWaterfallPoint`, every field optional so a series can mix the two kinds freely):
|
|
216
|
+
|
|
217
|
+
| Field | Meaning |
|
|
218
|
+
|---|---|
|
|
219
|
+
| `x` | Category label, timestamp, or `Date` |
|
|
220
|
+
| `y` | The **step**: the signed amount it moves the running total by. Omit on a subtotal / total row. |
|
|
221
|
+
| `isSubtotal` | Sum of the steps since the previous subtotal / total bar |
|
|
222
|
+
| `isTotal` | Sum of every step from zero |
|
|
223
|
+
| `fillColor` | Overrides the semantic fill for this row |
|
|
224
|
+
|
|
225
|
+
**`plotOptions.waterfall`:**
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
plotOptions: {
|
|
229
|
+
waterfall: {
|
|
230
|
+
colors: {
|
|
231
|
+
positive: '#00A86F', // a step that raises the running total
|
|
232
|
+
negative: '#FF4560', // a step that lowers it
|
|
233
|
+
subtotal: undefined, // defaults to the series color from the active palette
|
|
234
|
+
total: undefined, // same default, so running totals stay distinct from steps
|
|
235
|
+
},
|
|
236
|
+
connectors: {
|
|
237
|
+
show: true, // without them the floating columns read as unrelated bars
|
|
238
|
+
color: undefined, // defaults to grid.borderColor, so it is theme-aware
|
|
239
|
+
strokeWidth: 1,
|
|
240
|
+
strokeDashArray: 3,
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
A datum's own `fillColor` always wins over `plotOptions.waterfall.colors`.
|
|
247
|
+
|
|
248
|
+
### Dumbbell (v7.1)
|
|
249
|
+
|
|
250
|
+
`chart.type: 'dumbbell'` compares two or more measures per category. **Each series is one measure**, and the chart joins them with a connector per category. You do not zip the values into `[low, high]` pairs.
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
{
|
|
254
|
+
chart: { type: 'dumbbell', height: 350 },
|
|
255
|
+
series: [
|
|
256
|
+
{ name: '2020', data: [{ x: 'Backend', y: 92 }, { x: 'Frontend', y: 78 }] },
|
|
257
|
+
{ name: '2025', data: [{ x: 'Backend', y: 118 }, { x: 'Frontend', y: 96 }] },
|
|
258
|
+
],
|
|
259
|
+
plotOptions: { bar: { horizontal: true } }, // rows; omit for columns
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The connector's thickness is `plotOptions.bar.barHeight` (rows) or `columnWidth` (columns), and the size of the marked ends is `markers.size`: they are the bar and its markers, so they are configured as such.
|
|
264
|
+
|
|
265
|
+
**`plotOptions.bar.dumbbell`:**
|
|
266
|
+
|
|
267
|
+
```js
|
|
268
|
+
plotOptions: {
|
|
269
|
+
bar: {
|
|
270
|
+
dumbbell: {
|
|
271
|
+
connector: {
|
|
272
|
+
color: undefined, // undefined = a gradient between the two endpoint colours,
|
|
273
|
+
// resolved per row so a row where the measures cross runs the right way
|
|
274
|
+
opacity: 0.55, // the join is context for the marked ends, not a third mark
|
|
275
|
+
},
|
|
276
|
+
dataLabels: {
|
|
277
|
+
enabled: true, // default on for chart.type 'dumbbell', off for the bare isDumbbell flag
|
|
278
|
+
offset: 6, // px clear of the marked end, outward from the connector
|
|
279
|
+
colorFromMarker: true,
|
|
280
|
+
// formatter(value, { seriesIndex, dataPointIndex, endpointIndex, w })
|
|
281
|
+
// NOTE: defaults to the value axis' label formatter, NOT dataLabels.formatter
|
|
282
|
+
// (on a range bar that one reads out end - start, which is the gap, not the endpoint)
|
|
283
|
+
},
|
|
284
|
+
tooltip: { differenceLabel: 'Difference' },
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
With three or more measures only the two extremes are labelled: anything between them sits on the connector, where a label has nowhere to go that is not over the line or over its neighbour.
|
|
291
|
+
|
|
292
|
+
**Versus the older range-bar form.** `plotOptions.bar.isDumbbell` on a `rangeBar` with `y: [lo, hi]` pairs still works and is a different chart: one series, endpoint colours from `plotOptions.bar.dumbbellColors` (`[[startColor, endColor]]`). `chart.type: 'dumbbell'` takes one series per measure and colours each dot after the series it belongs to, from `colors`. Prefer the type unless you already have paired data.
|
|
293
|
+
|
|
187
294
|
---
|
|
188
295
|
|
|
189
296
|
## Key plotOptions.bar Options
|
|
@@ -197,7 +304,7 @@ plotOptions: {
|
|
|
197
304
|
distributed: false, // true = different color per data point
|
|
198
305
|
borderRadius: 4, // rounded corners (number or object)
|
|
199
306
|
borderRadiusApplication: 'end', // 'end' | 'around'
|
|
200
|
-
borderRadiusWhenStacked: '
|
|
307
|
+
borderRadiusWhenStacked: 'all', // 'all' (default) | 'last'; stacked bars only, see the note below
|
|
201
308
|
|
|
202
309
|
dataLabels: {
|
|
203
310
|
position: 'top', // 'top' | 'center' | 'bottom'
|
|
@@ -215,9 +322,22 @@ plotOptions: {
|
|
|
215
322
|
}
|
|
216
323
|
```
|
|
217
324
|
|
|
325
|
+
**⚠️ `borderRadiusWhenStacked`: dropped in v7.0, restored working in v7.4.** v7.0 removed it as dead config (it had not been read for some time) and let corner ownership follow the stack's **outer edge** automatically. v7.4 made it a real option again, so at v7.4+ it is live and must not be deleted from a config:
|
|
326
|
+
|
|
327
|
+
- `'all'` (the default) keeps the v7.0 look, both ends of the stack rounded. Existing charts are unchanged.
|
|
328
|
+
- `'last'` rounds only the far end and leaves the baseline square.
|
|
329
|
+
|
|
330
|
+
A stack of a single data point also stopped rounding its baseline in v7.4, which on a horizontal 100% stack with one category used to round the first segment on its inner edge. Related v7.0 fixes: a stacked bar's bottom cap is now the top-rounded path mirrored (caps no longer invert or pop when a series collapses and rises again), and grouped stacked charts resolve caps per group rather than chart-wide, so every group gets its own bottom and top radius.
|
|
331
|
+
|
|
332
|
+
**⚠️ `dataLabels.animate.enabled` now defaults to `true` (v7.0), bar/column only.** Labels ride to their new position on a data-change update instead of snapping there, so they reflow on the same clock as the bars, markers and axis ticks. A label that has not moved is a per-label no-op; speed and easing follow `chart.animations.dynamicAnimation`. For the pre-v7 behavior:
|
|
333
|
+
|
|
334
|
+
```js
|
|
335
|
+
dataLabels: { animate: { enabled: false } }
|
|
336
|
+
```
|
|
337
|
+
|
|
218
338
|
### Bar Chart Race (v6.4)
|
|
219
339
|
|
|
220
|
-
A reorder update animates into a bar chart race: when you re-sort the data and update the chart, the bars slide to their new ranks and their category labels ride along automatically (whenever `dynamicAnimation` is on). Two
|
|
340
|
+
A reorder update animates into a bar chart race: when you re-sort the data and update the chart, the bars slide to their new ranks and their category labels ride along automatically (whenever `dynamicAnimation` is on). Two `dataLabels` flags complete the effect, both **bar / column only**: `animate.enabled` is **on by default** since v7.0 (it was opt-in before), and `countUp.enabled` is off. their speed and easing follow `chart.animations.dynamicAnimation`.
|
|
221
341
|
|
|
222
342
|
```js
|
|
223
343
|
const options = {
|
|
@@ -309,4 +429,9 @@ series: [{
|
|
|
309
429
|
4. **Timeline without `xaxis.type: 'datetime'`** — date-based range bars need `xaxis: { type: 'datetime' }` to render correctly.
|
|
310
430
|
5. **`distributed: true` with multiple series** — distributed coloring applies to each data point independently. With multiple series, each point gets a unique color which is usually not desired. Use `distributed: true` only with single-series charts.
|
|
311
431
|
6. **Funnel/pyramid value ordering**: funnel expects values ordered largest-to-smallest and pyramid smallest-to-largest. The renderer does not sort for you; unsorted data produces a jagged shape. Stage labels come from `xaxis.categories`, and per-stage labels in `dataLabels.formatter` are read via `opt.w.globals.labels[opt.dataPointIndex]`.
|
|
312
|
-
7. **Reaching for `plotOptions.bar.isFunnel
|
|
432
|
+
7. **Reaching for `plotOptions.bar.isFunnel`**: unnecessary. Set `chart.type: 'funnel'` (or `'pyramid'`) and use `plotOptions.funnel` for shape options.
|
|
433
|
+
8. **Pre-computing the running total for a waterfall** *(v7.1)*: the series carries the **deltas**; the chart accumulates. Feeding it cumulative values draws each bar from zero to the total, which is a column chart with extra steps.
|
|
434
|
+
9. **Giving a waterfall subtotal row a `y`** *(v7.1)*: `isSubtotal` / `isTotal` rows are measured for you. Supply `x` and the flag, nothing else.
|
|
435
|
+
10. **Zipping dumbbell values into `y: [lo, hi]`** *(v7.1)*: that is the older `plotOptions.bar.isDumbbell` range-bar form. `chart.type: 'dumbbell'` wants one series per measure, each with plain `{ x, y }` points.
|
|
436
|
+
11. **Assuming `borderRadiusWhenStacked` is still removed**: it was dead config in v7.0 through v7.3 and is a working option again from v7.4 (`'all'` default, `'last'` to leave the baseline square). Guidance written for v7.0 says to delete it; on v7.4+ that silently reverts a deliberate `'last'` to `'all'`.
|
|
437
|
+
12. **Expecting data labels to snap on update** *(v7.0)*: `dataLabels.animate.enabled` now defaults to `true` on bar/column. Set it to `false` for the old behavior.
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- **Scatter** (`'scatter'`) — Individual data points plotted by X/Y coordinates
|
|
8
8
|
- **Bubble** (`'bubble'`) — Scatter with variable-size bubbles (requires z value)
|
|
9
9
|
- **Range Area** (`'rangeArea'`) — Area chart showing a range between two values
|
|
10
|
+
- **Streamgraph** (`'streamgraph'`, **new in v7.1**): Series stacked as flowing bands around a chosen baseline
|
|
10
11
|
|
|
11
12
|
## Tree-Shakeable Import
|
|
12
13
|
|
|
@@ -14,8 +15,13 @@
|
|
|
14
15
|
import ApexCharts from 'apexcharts/line'
|
|
15
16
|
// Registers: line, area, scatter, bubble, rangeArea
|
|
16
17
|
// Aliases: apexcharts/area, apexcharts/scatter, apexcharts/bubble, apexcharts/rangeArea
|
|
18
|
+
|
|
19
|
+
// streamgraph (v7.1) adds a feature module on top of the rangeArea engine:
|
|
20
|
+
import ApexCharts from 'apexcharts/streamgraph' // == apexcharts/rangeArea + features/streamgraph
|
|
17
21
|
```
|
|
18
22
|
|
|
23
|
+
Streamgraph is **Tier 1**, so the default `apexcharts` bundle already has it and no import is needed there.
|
|
24
|
+
|
|
19
25
|
---
|
|
20
26
|
|
|
21
27
|
## Data Formats (Detailed)
|
|
@@ -124,6 +130,62 @@ Always use XY format:
|
|
|
124
130
|
}
|
|
125
131
|
```
|
|
126
132
|
|
|
133
|
+
### Streamgraph (v7.1)
|
|
134
|
+
|
|
135
|
+
`chart.type: 'streamgraph'` stacks the series as flowing bands around a baseline chosen to keep the whole picture readable. Series format is the same as area; **the stacking is the chart's job, so do not set `chart.stacked`**.
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
{
|
|
139
|
+
chart: { type: 'streamgraph', height: 350 },
|
|
140
|
+
series: [
|
|
141
|
+
{ name: 'Drama', data: [{ x: '2024-01-01', y: 32 }, { x: '2024-02-01', y: 41 }] },
|
|
142
|
+
{ name: 'Comedy', data: [{ x: '2024-01-01', y: 18 }, { x: '2024-02-01', y: 26 }] },
|
|
143
|
+
],
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Curves are `monotoneCubic` by default so a band never overshoots its data, each band's name is drawn inside it sized to the room that band actually has, and hovering a band fades the others. The legend and tooltip work as on any axis chart.
|
|
148
|
+
|
|
149
|
+
**`plotOptions.streamgraph`:**
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
plotOptions: {
|
|
153
|
+
streamgraph: {
|
|
154
|
+
offset: 'wiggle', // where the baseline goes:
|
|
155
|
+
// 'wiggle' (default) minimizes total weighted slope, so thick bands stay level
|
|
156
|
+
// 'silhouette' centres the stack on one horizontal line
|
|
157
|
+
// 'zero' an ordinary stacked area, on the zero line
|
|
158
|
+
// 'expand' normalizes each column to its own total (composition, not volume)
|
|
159
|
+
|
|
160
|
+
order: 'inside-out', // stacking order, bottom first:
|
|
161
|
+
// 'inside-out' (default) puts early-peaking series in the middle and fans
|
|
162
|
+
// later peaks outward, each to whichever side is thinner
|
|
163
|
+
// 'inverse' the series order, reversed
|
|
164
|
+
// 'none' the series order as given
|
|
165
|
+
|
|
166
|
+
hover: { show: true, opacity: 0.35 }, // what the OTHER bands drop to; much above ~0.5 and the
|
|
167
|
+
// hovered band stops reading as picked out
|
|
168
|
+
|
|
169
|
+
labels: {
|
|
170
|
+
show: true,
|
|
171
|
+
minWidth: 24, // a band narrower than this many px is left unlabelled rather than
|
|
172
|
+
// given a name truncated past the point of being a name
|
|
173
|
+
minFontSize: 9,
|
|
174
|
+
maxFontSize: 30,
|
|
175
|
+
style: {
|
|
176
|
+
fontSize: 'auto', // sizes each name to its band, bounded by min/maxFontSize.
|
|
177
|
+
// Give a literal ('12px') to draw every name at the same size.
|
|
178
|
+
fontWeight: 600,
|
|
179
|
+
colors: undefined, // per-series override; by default each label takes black or white,
|
|
180
|
+
// whichever reads on its own band
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
`offset: 'wiggle'` with `order: 'inside-out'` is the classic streamgraph, and the pair is what keeps it readable: the middle of the stack moves least under a wiggle baseline. A faded band's name is recoloured to `chart.foreColor` rather than faded with it, because the name takes black or white by the contrast of the band at full strength.
|
|
188
|
+
|
|
127
189
|
---
|
|
128
190
|
|
|
129
191
|
## Key Options
|
|
@@ -192,6 +254,25 @@ xaxis: {
|
|
|
192
254
|
}
|
|
193
255
|
```
|
|
194
256
|
|
|
257
|
+
### A way out of a zoom when the toolbar is hidden (v7.4)
|
|
258
|
+
|
|
259
|
+
Hiding the toolbar does not disable drag-to-zoom (a drag is a deliberate gesture, unlike the wheel and the pinch), so a viewer can zoom a bare chart and then have nothing on screen that puts the range back.
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
chart: {
|
|
263
|
+
toolbar: { show: false },
|
|
264
|
+
zoom: { enabled: true, resetControl: 'auto' } // 'auto' is the default
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
While the chart **is** zoomed and nothing else can reset it, one reset control is drawn where the toolbar would have been, and it goes when the range does. `Escape` resets under the same gate, and the event is left alone so a page listening for it still hears it.
|
|
269
|
+
|
|
270
|
+
- `'auto'` (default): supply both only where there is no reset button already. A chart nobody zooms is untouched, so `toolbar: { show: false }` still means an empty chart for every viewer who does not zoom.
|
|
271
|
+
- `true`: also force the control on where `toolbar.tools.reset` is off, which is the same dead end as a hidden toolbar.
|
|
272
|
+
- `false`: turn off both the control and the key, for a page that supplies its own reset.
|
|
273
|
+
|
|
274
|
+
Requires `zoom.enabled: true`. A completed drag-zoom now also focuses the chart, so the `+`, `-` and `0` keys are reachable straight after a mouse zoom.
|
|
275
|
+
|
|
195
276
|
---
|
|
196
277
|
|
|
197
278
|
## Complete Working Example — Line Chart with Datetime
|
|
@@ -242,6 +323,20 @@ xaxis: {
|
|
|
242
323
|
|
|
243
324
|
1. **Bubble chart without z value** — renders with zero-size bubbles. Always provide `z` in data.
|
|
244
325
|
2. **Using `xaxis.categories` with `{ x, y }` data** — categories are silently ignored when data contains x values. Choose one approach.
|
|
245
|
-
3. **Datetime axis with string dates
|
|
326
|
+
3. **Datetime axis with string dates**: pass timestamps (`new Date(...).getTime()`) or `Date` objects, not raw strings like `'January 2024'`. Since v6.10 a `Date` object `x` is accepted by the types and keeps millisecond resolution (previously milliseconds were truncated, collapsing points within the same second). **Since v7.1 a `Date` x also works on a non-datetime axis**; before that it only worked when the axis was `datetime` and stringified into garbage anywhere else, and an invalid `Date` slipped through unnoticed. Both are handled now.
|
|
246
327
|
4. **`stroke.curve: 'smooth'` on sparse data** — can produce visual artifacts. Use `'monotoneCubic'` for mathematically smoother interpolation.
|
|
247
328
|
5. **Range Area with single value instead of array** — `y` must be `[low, high]`, not a single number.
|
|
329
|
+
6. **Setting `chart.stacked` on a streamgraph** *(v7.1)*: the chart owns its own stacking, baseline and band order through `plotOptions.streamgraph`. Reach for `offset: 'zero'` if what you actually want is a plain stacked area.
|
|
330
|
+
7. **A series that starts with nulls used to mis-target the tooltip**: the hovered index resolved against the drawn points rather than the data, so the tooltip read the wrong point. Fixed in v7.1.
|
|
331
|
+
8. **`autoScaleYaxis` scaling to points nobody can see**: before v7.1, zooming let one point just outside the window size the whole axis, and a series with nothing in the window still contributed. Fixed in v7.1; stacked charts now also scale to the stacked totals inside the window rather than to individual series.
|
|
332
|
+
|
|
333
|
+
## Axis and layout fixes worth knowing (v7.0 / v7.1)
|
|
334
|
+
|
|
335
|
+
These need no config change; they matter because a workaround you carried from an earlier version may now be unnecessary.
|
|
336
|
+
|
|
337
|
+
- **Logarithmic axis geometry, and `tickAmount` on a log scale** *(v7.0)*. Log-scale positions were computed against the wrong domain, and `tickAmount` was ignored outright on a log axis. Both fixed, so `yaxis: { logarithmic: true, tickAmount: n }` now does what it says.
|
|
338
|
+
- **Bar width came from the smallest gap inside one series** *(fixed v7.1)*. A single series with one tight pair of x values shrank every bar on the chart. A bar's slot now comes from the axis, the union of gaps across all series.
|
|
339
|
+
- **Stacked baselines resolve by x, not by position in the array** *(fixed v7.0)*. Two series stacked on ragged data lined up by ordinal, so a series with a missing point stacked onto the wrong neighbour.
|
|
340
|
+
- **A container resize arriving mid-animation was lost for good** *(fixed v7.1)*. The ResizeObserver fires once per resize and the handler dropped that callback while an animation ran, so a chart in a collapsing sidebar kept its old size.
|
|
341
|
+
- **Annotations on a chart with no data** *(fixed v7.0)*. Placement was gated chart-wide on `dataPoints`, so an empty chart dropped every annotation including y-axis ones that are always placeable. Gating is now per annotation.
|
|
342
|
+
- **A tooltip inside Shadow DOM followed the wrong element** *(fixed v7.0)*. Reading `e.target` after a deferred hover gets the shadow host, not the hovered mark.
|
|
@@ -29,8 +29,13 @@ import ApexCharts from 'apexcharts/unit'
|
|
|
29
29
|
|
|
30
30
|
import { heart, outlined, glyphs, preview } from 'apexcharts/unit-shapes'
|
|
31
31
|
// Unit-chart shape kit (v6.10), named exports tree-shaken per shape. See "Unit shapes" below.
|
|
32
|
+
|
|
33
|
+
import { person, registerMarks } from 'apexcharts/pictograms'
|
|
34
|
+
// Pictogram glyph collection (v7.0), one drawn mark per unit. See "Pictograms" below.
|
|
32
35
|
```
|
|
33
36
|
|
|
37
|
+
All of these are **Tier 1** (in the default `apexcharts` bundle). Nothing in the circular family is Tier 2.
|
|
38
|
+
|
|
34
39
|
---
|
|
35
40
|
|
|
36
41
|
## Data Format
|
|
@@ -150,9 +155,13 @@ A sunburst draws a hierarchy as concentric rings: the first level fills a donut
|
|
|
150
155
|
|
|
151
156
|
Colours, `stroke`, `legend`, and `title` behave as they do on pie and donut. A sunburst can also adapt an existing `drilldown` config instead of a native `children` hierarchy.
|
|
152
157
|
|
|
158
|
+
A branch may **omit its own `y`** and be the sum of its children. That is the documented shape, but it only began working in v7.6: before that the non-axis parser required every datum to carry `x` and `y`, so a branch with only `children` was dropped, the series came back empty, and the chart drew nothing while warning about pie data. The samples all gave their top-level nodes a `y`, which is what hid it from the moment sunburst shipped.
|
|
159
|
+
|
|
160
|
+
**The same tree in cartesian coordinates** is the `icicle` type *(v7.6)*: one band per depth level instead of concentric rings, labels horizontal at every depth, and `direction: 'up'` for flame graphs. It is an opt-in import. See `references/grid-charts.md`.
|
|
161
|
+
|
|
153
162
|
### Unit / Waffle (v6.6, premium)
|
|
154
163
|
|
|
155
|
-
A `unit` chart renders one discrete mark for every unit of value instead of a single bar or slice, so "37 of 200" reads as a countable quantity. It is a **non-axis** chart (dispatched like pie or treemap) and is **premium**: it renders fully in trial mode with an `APEXCHARTS` watermark until an entitled license is set (see `references/
|
|
164
|
+
A `unit` chart renders one discrete mark for every unit of value instead of a single bar or slice, so "37 of 200" reads as a countable quantity. It is a **non-axis** chart (dispatched like pie or treemap) and is **premium**: it renders fully in trial mode with an `APEXCHARTS` watermark until an entitled license is set (see `references/feature-platform.md`). On every update each mark tweens from its old position to its new one, so re-grouping, filtering, or a changing count re-forms the marks.
|
|
156
165
|
|
|
157
166
|
Data is the same flat number array + `labels` shape as pie:
|
|
158
167
|
|
|
@@ -219,6 +228,45 @@ registerShapes([...]) // register so positions: '<name>' resolves by
|
|
|
219
228
|
|
|
220
229
|
Every shape carries metadata on `shape` (category, kind, and `minUnits`: the count below which it stops being recognisable; asking for fewer logs a console warning naming the shape). From a script tag, `dist/unit-shapes.js` exposes the kit as the global `ApexUnitShapes` with every shape pre-registered, so `positions: 'heart'` works by name.
|
|
221
230
|
|
|
231
|
+
### Pictograms (`apexcharts/pictograms`, v7.0)
|
|
232
|
+
|
|
233
|
+
A **shape** is where the units go; a **pictogram** is what one unit looks like. They are independent, so `positions: heart` with `shape: 'pictogram'` arranges glyphs into a heart, and every other pairing is equally valid.
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
import ApexCharts from 'apexcharts'
|
|
237
|
+
import { person, registerMarks } from 'apexcharts/pictograms'
|
|
238
|
+
|
|
239
|
+
registerMarks([person]) // so pictogram.mark: 'person' resolves by name
|
|
240
|
+
|
|
241
|
+
const options = {
|
|
242
|
+
chart: { type: 'unit' },
|
|
243
|
+
series: [120, 80],
|
|
244
|
+
labels: ['Employed', 'Unemployed'],
|
|
245
|
+
plotOptions: {
|
|
246
|
+
unit: {
|
|
247
|
+
shape: 'pictogram',
|
|
248
|
+
pictogram: {
|
|
249
|
+
mark: 'person', // a registered name, a { path, viewBox?, fillRule? } object,
|
|
250
|
+
// raw path data, or an array (one per series).
|
|
251
|
+
// A datum's own `mark` overrides all of it, so one crowd can mix glyphs.
|
|
252
|
+
fit: 'contain', // which side of the glyph binds to the dot's box: 'contain' | 'width' | 'height'
|
|
253
|
+
scale: 1, // nudge for glyphs that read light
|
|
254
|
+
padding: 0, // 0..0.9 of the pitch, opening the lattice up
|
|
255
|
+
fallback: 'circle', // drawn when a mark cannot be resolved
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
A glyph is drawn as one `<path>` per unit, filled in that unit's own colour: no request, no decode, no recolour filter, which is why `'pictogram'` is the shape that scales to thousands of units. There is deliberately **no size**: a glyph is fitted to the box the dot itself would have occupied, so `plotOptions.unit.size` and `spacing` size a pictogram exactly as they size a dot.
|
|
263
|
+
|
|
264
|
+
**Shipped glyphs** (each a named export, so import the one you use): `person`, `house`, `heart`, `tree`, `droplet`, `star`, `car`, `bag`, `book`, `cup`, `bulb`, `plane`. `catalog` is every glyph and ships all of them, so avoid it in an app bundle.
|
|
265
|
+
|
|
266
|
+
**Custom glyphs:** `definePictogram({ name, path, viewBox?, fillRule?, category?, source? })` builds one, `registerMarks(defs)` registers them by name, `unregisterMarks(names)` removes them, and `registeredMarkNames()` lists what resolves. Any glyph also has `.with(overrides)` for a variant with some metadata replaced.
|
|
267
|
+
|
|
268
|
+
**Versus `shape: 'image'`:** `'image'` fetches a raster or multi-colour icon (`plotOptions.unit.image.src`, with `tint: true` to recolour a monochrome icon to the category colour). Use it for multi-colour marks that should keep their own colours; use `'pictogram'` for anything that has to scale or follow the palette.
|
|
269
|
+
|
|
222
270
|
**Outer name labels (v6.10):** a shape packed with several categories can name them in the margin with a leader line to their own dots (the pie/donut outer-label mechanism), instead of needing a legend:
|
|
223
271
|
|
|
224
272
|
```js
|
|
@@ -445,3 +493,6 @@ plotOptions: {
|
|
|
445
493
|
10. **Expecting `unit` / `waffle` without a license to be watermark-free**: they are premium and render an `APEXCHARTS` watermark until an entitled `premium`/`enterprise` license is set. Sunburst, by contrast, is free.
|
|
446
494
|
11. **Slice click behavior changed (v6.9)**: clicking a pie/donut slice now slides it out along its own mid-angle (`plotOptions.pie.expandOffset`, default 10 px) instead of darkening it and redrawing it at a larger radius, and hover traces an outline band (`plotOptions.pie.hoverOutline`) instead of lightening the fill. Set `expandOffset: 0` to keep slices in place; set `states.hover.filter.type: 'none'` to suppress the hover band.
|
|
447
495
|
12. **Unit shapes below `minUnits`**: each `apexcharts/unit-shapes` shape declares the minimum dot count at which it still reads. Feeding fewer units logs a console warning naming the shape; pick a simpler shape or raise `unitValue` so the count lands above the threshold.
|
|
496
|
+
13. **Confusing a shape with a pictogram** *(v7.0)*: `plotOptions.unit.positions` (from `apexcharts/unit-shapes`) is **where** the units go; `plotOptions.unit.shape: 'pictogram'` + `pictogram.mark` (from `apexcharts/pictograms`) is **what one unit looks like**. They compose freely.
|
|
497
|
+
14. **Setting a size on a pictogram** *(v7.0)*: there is no `pictogram.size`. A glyph is fitted to the box the dot would have occupied, so use `plotOptions.unit.size` and `spacing`. Use `pictogram.scale` only to nudge a glyph that reads light.
|
|
498
|
+
15. **Pie / radial charts pinned to the top of a tall container** *(fixed v7.1)*: the centre came from `min(width, height)`, so a tall, narrow container put the circle at the top with the leftover space below it. The circle now centres in the height it actually has. If you carried a manual `offsetY` to work around this, remove it.
|