apexcharts-skill 4.0.2 → 4.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 +14 -10
- package/README.md +1 -1
- package/SKILL.md +36 -19
- package/package.json +1 -1
- package/references/bar-charts.md +7 -3
- package/references/cartesian-charts.md +29 -0
- package/references/circular-charts.md +55 -2
- package/references/feature-platform.md +45 -13
- package/references/framework-wrappers.md +8 -7
- package/references/grid-charts.md +7 -1
- package/references/ssr.md +6 -0
- package/references/tree-shaking.md +5 -4
package/.cursorrules
CHANGED
|
@@ -16,14 +16,14 @@ v5 and v6 configs keep working, with two v7.0 changes: `plotOptions.bar.borderRa
|
|
|
16
16
|
import 'apexcharts/features/drilldown' // a Tier 2 feature
|
|
17
17
|
|
|
18
18
|
Tier 2 chart types, `import 'apexcharts/<type>'` (script tag `dist/<type>.js`): `unit` (also for `waffle`), `sunburst` and `violin` (all three since 8.0), `icicle` (7.6), and `raincloud` (`apexcharts/raincloud` brings violin plus the raincloud feature; script tags `dist/violin.js`, then `dist/features/raincloud.js`).
|
|
19
|
-
Tier 2 features, `import 'apexcharts/features/<name>'` (script tag `dist/features/<name>.js`): drilldown, waterfall, dumbbell, streamgraph (since 8.0), highlight-filter (7.9), trellis, storyboard, perspectives, ink, renderer-canvas, link, measure, history, context-menu (since 7.0). Waterfall, dumbbell and streamgraph are chart types whose renderer is in the default bundle, so next to it add only the feature.
|
|
19
|
+
Tier 2 features, `import 'apexcharts/features/<name>'` (script tag `dist/features/<name>.js`): radial-targets (8.5, for `plotOptions.radialBar.targets`), drilldown, waterfall, dumbbell, streamgraph (since 8.0), highlight-filter (7.9), trellis, storyboard, perspectives, ink, renderer-canvas, link, measure, history, context-menu (since 7.0). Waterfall, dumbbell and streamgraph are chart types whose renderer is in the default bundle, so next to it add only the feature.
|
|
20
20
|
`apexcharts/features/all` is the Tier 1 set and pulls in none of them.
|
|
21
21
|
Full bundle (v8.0): `import ApexCharts from 'apexcharts/full'` (script tag `dist/apexcharts.full.min.js`) carries every chart type and feature and needs no add-on import. Gzipped at 8.0.0: default bundle 263,188 B, full bundle 381,135 B.
|
|
22
|
-
A missing import is named in the console: a Tier 2 chart type makes `render()` reject; a waterfall, dumbbell or streamgraph draws an empty plot; a Tier 2 feature degrades where it can (a trellis renders as one chart; renderer: 'canvas' falls back to SVG). Unversioned CDN URLs serve 8.
|
|
22
|
+
A missing import is named in the console: a Tier 2 chart type makes `render()` reject; a waterfall, dumbbell or streamgraph draws an empty plot; a Tier 2 feature degrades where it can (a trellis renders as one chart; renderer: 'canvas' falls back to SVG; a gauge draws without its targets). Unversioned CDN URLs serve the latest 8.x release; pin a 7.x release to stay on 7.
|
|
23
23
|
|
|
24
|
-
Premium (watermarked until an entitled premium/enterprise license): trellis, storyboard, link, ink, measure, context-menu, perspectives, history, highlight-filter, and the unit/waffle and raincloud chart types. Premium and Tier 2 are separate axes: since 8.0 every premium item is Tier 2, but renderer-canvas, drilldown, waterfall, dumbbell, streamgraph, sunburst, violin and icicle are Tier 2 and free.
|
|
24
|
+
Premium (watermarked until an entitled premium/enterprise license): trellis, storyboard, link, ink, measure, context-menu, perspectives, history, highlight-filter, and the unit/waffle and raincloud chart types. Premium and Tier 2 are separate axes: since 8.0 every premium item is Tier 2, but renderer-canvas, drilldown, radial-targets, waterfall, dumbbell, streamgraph, sunburst, violin and icicle are Tier 2 and free.
|
|
25
25
|
|
|
26
|
-
On by default: coherent add/remove data-transition animations (they respect prefers-reduced-motion), and one-finger kinetic pan (`chart.pan.inertia`). Since v7.8, `dataLabels.avoidOverlap` nudges overlapping data labels apart (`false` to disable). Pinch-zoom and two-finger pan follow `chart.zoom.pinch: 'auto'`: on only where the toolbar reset button is present.
|
|
26
|
+
On by default: coherent add/remove data-transition animations (they respect prefers-reduced-motion), and one-finger kinetic pan (`chart.pan.inertia`). Since v7.8, `dataLabels.avoidOverlap` nudges overlapping data labels apart (`false` to disable). Pinch-zoom and two-finger pan follow `chart.zoom.pinch: 'auto'`: on only where the toolbar reset button is present. The mouse wheel follows `chart.zoom.allowMouseWheelZoom: 'auto'`, the same gate, and since v8.3 it is cooperative: a bare wheel scrolls the page (with a short hint, `chart.zoom.wheelHint: false` hides it), and Ctrl/Cmd + wheel or a trackpad pinch zooms. `allowMouseWheelZoom: true` zooms on every wheel.
|
|
27
27
|
|
|
28
28
|
## Framework wrapper detection — check `package.json` first
|
|
29
29
|
|
|
@@ -41,7 +41,7 @@ Wrappers handle `destroy()` automatically on unmount, accept reactive props, and
|
|
|
41
41
|
4. **`yaxis` must be an array** when using multiple y-axes. Each entry needs `seriesName`.
|
|
42
42
|
5. **`tooltip.shared` and `tooltip.intersect` are mutually exclusive.**
|
|
43
43
|
6. **Use `null` (not `undefined`)** for missing data points.
|
|
44
|
-
7. **`chart.stacked: true`** stacks `bar`, `area` and `line` series. In a mixed chart only the bar series stack unless `chart.stackOnlyBar: false`. `waterfall`, `dumbbell` and `streamgraph` force it off.
|
|
44
|
+
7. **`chart.stacked: true`** stacks `bar`, `area` and `line` series. In a mixed chart only the bar series stack unless `chart.stackOnlyBar: false`. `waterfall`, `dumbbell` and `streamgraph` force it off. `chart.stackType: '100%'` draws shares of each stack's total; since v8.5 area and line stacks draw percentages too.
|
|
45
45
|
8. **Responsive breakpoints** must be in ascending order.
|
|
46
46
|
9. **For mixed/combo charts**, set `type` on each series object.
|
|
47
47
|
10. **RadialBar values sit on the `plotOptions.radialBar.min` to `max` domain** (default 0 to 100, so percentages by default). Set `min` / `max` to plot raw values; a value outside the domain is clamped.
|
|
@@ -50,9 +50,9 @@ Wrappers handle `destroy()` automatically on unmount, accept reactive props, and
|
|
|
50
50
|
13. **Tree-shaking**: `apexcharts/core` requires separate chart-type + feature imports. On it, `violin` and `raincloud` also need `apexcharts/bar`, and a raw-sample boxPlot or violin needs `apexcharts/features/stats`.
|
|
51
51
|
14. **Aliases**: `funnel`/`pyramid` render through bar, `gauge` through radialBar. Use them as `chart.type` directly (no `plotOptions.bar.isFunnel`); covered by `apexcharts/bar` and `apexcharts/radialBar`.
|
|
52
52
|
15. **`violin`** points use a density profile: `data: [{ x, y: { density: [[value, weight], ...], points?: [num] } }]`.
|
|
53
|
-
16. **`render()` is idempotent**: a repeated `render()` returns the same promise; still `destroy()` before a new instance on the same element.
|
|
53
|
+
16. **`render()` is idempotent**: a repeated `render()` returns the same promise; still `destroy()` before a new instance on the same element. Since v8.1 `render()` after `destroy()` draws that instance afresh, and `updateOptions` / `updateSeries` on a destroyed chart warn and resolve instead of throwing.
|
|
54
54
|
17. **Unknown `chart.type` throws (v7.9)** and the message names the closest type. `'column'` is a synonym for `'bar'`; `''` and `null` draw a line chart.
|
|
55
|
-
18. **A script tag names the exact version shown here**: `https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
55
|
+
18. **A script tag names the exact version shown here**: `https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/apexcharts.min.js` or `https://cdn.jsdelivr.net/npm/apexcharts@8.6.0/dist/apexcharts.min.js`. Never write a 3.x or 4.x URL (`.../apexcharts/3.54.1/...`): those are releases from 2024 and early 2025. If the environment only accepts an older release, use the newest one it accepts with the same major version as these URLs.
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
@@ -179,6 +179,7 @@ apexcharts/features/waterfall # (v7.1) waterfall type (Tier 2 since v8)
|
|
|
179
179
|
apexcharts/features/dumbbell # (v7.1) dumbbell type (Tier 2 since v8)
|
|
180
180
|
apexcharts/features/streamgraph # (v7.1) streamgraph type (Tier 2 since v8)
|
|
181
181
|
apexcharts/features/highlight-filter # (v7.9) part-of-whole highlight, highlightFilter (premium)
|
|
182
|
+
apexcharts/features/radial-targets # (v8.5) plotOptions.radialBar.targets on radialBar / gauge (free)
|
|
182
183
|
apexcharts/features/trellis # (v7.0) small multiples (premium)
|
|
183
184
|
apexcharts/features/storyboard # scrollytelling (premium; registers perspectives)
|
|
184
185
|
apexcharts/features/perspectives # shareable view state (premium)
|
|
@@ -202,13 +203,15 @@ Lean core channel (v7.0): `dist/apexcharts.core.js` plus per-type files such as
|
|
|
202
203
|
| `xaxis.labels.formatter` | `(value, timestamp?, opts?) => string` |
|
|
203
204
|
| `yaxis.labels.formatter` | `(value, opts?) => string` |
|
|
204
205
|
| `tooltip.x.formatter` | `(value, opts?) => string` |
|
|
205
|
-
| `tooltip.y.formatter` | `(value: number \| null, opts?) => string`; `value` is `null` at a gap, so guard: `val == null ? 'n/a' : val.toFixed(2)` |
|
|
206
|
+
| `tooltip.y.formatter` | `(value: number \| null, opts?) => string \| null`; `value` is `null` at a gap, so guard: `val == null ? 'n/a' : val.toFixed(2)`. Returning `null` hides that row in a shared tooltip |
|
|
206
207
|
| `tooltip.y.title.formatter` | `(seriesName, opts?) => string` |
|
|
207
208
|
| `dataLabels.formatter` | `(value, opts?) => string \| number` |
|
|
208
|
-
| `legend.formatter` | `(legendName, opts?) => string` |
|
|
209
|
+
| `legend.formatter` | `(legendName, opts?) => string` (HTML; `legendName` is raw, so escape it before adding markup) |
|
|
209
210
|
| `plotOptions.pie.donut.labels.total.formatter` | `(w) => string` |
|
|
210
211
|
| `plotOptions.radialBar.dataLabels.value.formatter` | `(val) => string` |
|
|
211
212
|
|
|
213
|
+
Names are text (v8.4): series names, categories, goal names and tree node names are escaped in the legend and tooltip, so markup in them shows literally. Markup a formatter returns still renders.
|
|
214
|
+
|
|
212
215
|
---
|
|
213
216
|
|
|
214
217
|
## Pitfalls — ❌ Wrong vs ✅ Correct
|
|
@@ -234,8 +237,9 @@ Lean core channel (v7.0): `dist/apexcharts.core.js` plus per-type files such as
|
|
|
234
237
|
✅ `yaxis: [{ seriesName: 'Revenue', title: {...} }, { seriesName: 'Profit', opposite: true }]`
|
|
235
238
|
|
|
236
239
|
### 6. Both shared and intersect tooltips
|
|
237
|
-
❌ `tooltip: { shared: true, intersect: true }`
|
|
240
|
+
❌ `tooltip: { shared: true, intersect: true }` (constructing the chart throws)
|
|
238
241
|
✅ `tooltip: { shared: true, intersect: false }` or `{ shared: false, intersect: true }`
|
|
242
|
+
`tooltip.visible: false` (v8.5) keeps hover events and crosshairs but draws no tooltip box; `enabled: false` turns hover off.
|
|
239
243
|
|
|
240
244
|
### 7. undefined for missing data
|
|
241
245
|
❌ `data: [10, undefined, 30]`
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ This skill targets **ApexCharts v8** (v5, v6 and v7 configs keep working, apart
|
|
|
27
27
|
- **30 `chart.type` values**: line, area, bar (with its `column` synonym), pie, donut, radialBar, scatter, bubble, heatmap, candlestick, boxPlot, violin, histogram, radar, polarArea, rangeBar, rangeArea, treemap, funnel, pyramid, gauge, sunburst, icicle, unit, waffle, waterfall, dumbbell, streamgraph, raincloud
|
|
28
28
|
- **Correct data formats** for every chart type
|
|
29
29
|
- **Common pitfalls** with wrong/correct code examples
|
|
30
|
-
- **Feature platform**: small multiples (Trellis), plugins (Weave), canvas renderer (Strata), custom series (Marks), undo/redo (Rewind), shareable views (Perspectives), themes (Facet), easing (Cadence), crossfilter (Link), annotation authoring (Ink), measure ruler, context menu, storyboard, streaming, drilldown, part-of-whole highlight (Highlight filter), raw-sample statistics (Stats), unit-chart shape kit (`apexcharts/unit-shapes`), pictogram glyphs (`apexcharts/pictograms`)
|
|
30
|
+
- **Feature platform**: small multiples (Trellis), plugins (Weave), canvas renderer (Strata), custom series (Marks), undo/redo (Rewind), shareable views (Perspectives), themes (Facet), easing (Cadence), crossfilter (Link), annotation authoring (Ink), measure ruler, context menu, storyboard, streaming, drilldown, part-of-whole highlight (Highlight filter), radialBar and gauge targets (8.5), raw-sample statistics (Stats), unit-chart shape kit (`apexcharts/unit-shapes`), pictogram glyphs (`apexcharts/pictograms`)
|
|
31
31
|
- **Bundle contents** (which chart types and features the default v8 bundle carries, which are opt-in imports, and the `apexcharts/full` bundle), tree-shaking, and the lean-core script-tag channel
|
|
32
32
|
- **SSR** (server-side rendering) and hydration
|
|
33
33
|
- **Framework integration**: React, Vue 3, Angular
|
package/SKILL.md
CHANGED
|
@@ -9,14 +9,14 @@ description: >
|
|
|
9
9
|
correct data formats, lifecycle, formatters, tree-shaking, SSR, and the feature
|
|
10
10
|
platform (plugins, canvas renderer, custom series, small multiples, undo/redo,
|
|
11
11
|
shareable views, themes, crossfilter, annotation authoring, storyboard, streaming,
|
|
12
|
-
drilldown, highlight filter). Knows which chart types and features ship in the
|
|
12
|
+
drilldown, highlight filter, radialBar targets). Knows which chart types and features ship in the
|
|
13
13
|
default v8 bundle and which need an explicit import or the full bundle. In React /
|
|
14
14
|
Vue / Angular projects, prefer the framework wrapper packages
|
|
15
15
|
(`react-apexcharts`, `vue3-apexcharts`, `ng-apexcharts`) over the core API.
|
|
16
16
|
metadata:
|
|
17
17
|
author: ApexCharts
|
|
18
|
-
version: "4.0
|
|
19
|
-
library_version: "8.
|
|
18
|
+
version: "4.1.0"
|
|
19
|
+
library_version: "8.7.0"
|
|
20
20
|
category: data-visualization
|
|
21
21
|
tags: [charts, visualization, javascript, typescript, svg, apexcharts]
|
|
22
22
|
docs: https://apexcharts.com/docs/
|
|
@@ -57,19 +57,20 @@ metadata:
|
|
|
57
57
|
> | `raincloud` | `apexcharts/raincloud` (the violin renderer plus the raincloud feature) | `dist/violin.js`, then `dist/features/raincloud.js` | 7.1 (new); needs violin since 8.0 |
|
|
58
58
|
> | `drilldown`, and the `waterfall`, `dumbbell` and `streamgraph` chart types | `apexcharts/features/<name>` | `dist/features/<name>.js` | 8.0 |
|
|
59
59
|
> | `highlight-filter` (`highlightFilter`) | `apexcharts/features/highlight-filter` | `dist/features/highlight-filter.js` | 7.9 (new) |
|
|
60
|
+
> | `radial-targets` (`plotOptions.radialBar.targets`) | `apexcharts/features/radial-targets` | `dist/features/radial-targets.js` | 8.5 (new) |
|
|
60
61
|
> | `trellis`, `storyboard`, `perspectives`, `ink`, `renderer-canvas`, `link`, `measure`, `history`, `context-menu` | `apexcharts/features/<name>` | `dist/features/<name>.js` | 7.0 |
|
|
61
62
|
>
|
|
62
63
|
> Waterfall and dumbbell draw through rangeBar and streamgraph through rangeArea, which the default bundle has, so next to it you add only the feature. Storyboard registers Perspectives, so importing both costs no more than Storyboard alone.
|
|
63
64
|
>
|
|
64
65
|
> **The full bundle** (v8.0) loads everything at once: `import ApexCharts from 'apexcharts/full'` in a bundler, `dist/apexcharts.full.min.js` from a script tag. It carries every chart type and feature plus the unit-shapes and pictograms catalogs, and needs no add-on import (premium items stay license-gated). Gzipped at 8.0.0: default bundle 263,188 B, full bundle 381,135 B.
|
|
65
66
|
>
|
|
66
|
-
> **Nothing fails silently**: when the import is missing, the console names it. A Tier 2 chart type makes `render()` reject; a `waterfall`, `dumbbell` or `streamgraph` draws an empty plot; a Tier 2 feature degrades where it can (a trellis renders as one chart; `renderer: 'canvas'` falls back to SVG). Unversioned CDN URLs serve 8.
|
|
67
|
+
> **Nothing fails silently**: when the import is missing, the console names it. A Tier 2 chart type makes `render()` reject; a `waterfall`, `dumbbell` or `streamgraph` draws an empty plot; a Tier 2 feature degrades where it can (a trellis renders as one chart; `renderer: 'canvas'` falls back to SVG; a gauge draws without its targets). Unversioned CDN URLs serve the latest 8.x release; pin a 7.x release to stay on 7, where unit, sunburst, violin, drilldown, waterfall, dumbbell and streamgraph are still in the default bundle. The split began in v7.0, which moved the nine features in the last table row out of a default bundle that had carried every feature. See `references/tree-shaking.md` for the full tier table and `references/feature-platform.md` for each feature's API.
|
|
67
68
|
>
|
|
68
69
|
> **Other v7.0 breaking changes.** (1) `plotOptions.bar.borderRadiusWhenStacked` was dropped as dead config in v7.0 and is a **working option again in v7.4**: `'all'` (the default) rounds both stack ends, `'last'` rounds only the far end and leaves the baseline square. Do not delete it from a config. (2) `dataLabels.animate.enabled` now defaults to `true` (bar/column only): labels ride to their new position on a data update instead of snapping. Set `dataLabels: { animate: { enabled: false } }` for the old behavior. Everything else from v5 and v6 keeps working unchanged.
|
|
69
70
|
>
|
|
70
|
-
> **Behaviors that are on by default** (both respect `prefers-reduced-motion`): data updates that add/remove points animate coherently, and one-finger kinetic pan is enabled (`chart.pan.inertia`). Since v7.8, data labels that land on each other are nudged apart (`dataLabels.avoidOverlap`, see section 5). The two-finger gestures, pinch-zoom and two-finger pan, sit behind `chart.zoom.pinch`, which defaults to `'auto'`: **on only where the toolbar reset button is present**, so an unintended zoom is always undoable. `chart.zoom.allowMouseWheelZoom` is gated the same way. Set `pinch: true` to force the gestures on a toolbar-less chart, or see `chart.zoom.resetControl` (v7.4) for the other way to satisfy the gate.
|
|
71
|
+
> **Behaviors that are on by default** (both respect `prefers-reduced-motion`): data updates that add/remove points animate coherently, and one-finger kinetic pan is enabled (`chart.pan.inertia`). Since v7.8, data labels that land on each other are nudged apart (`dataLabels.avoidOverlap`, see section 5). The two-finger gestures, pinch-zoom and two-finger pan, sit behind `chart.zoom.pinch`, which defaults to `'auto'`: **on only where the toolbar reset button is present**, so an unintended zoom is always undoable. `chart.zoom.allowMouseWheelZoom` is gated the same way, and **since v8.3 its `'auto'` wheel is cooperative**: a bare wheel scrolls the page past the chart (showing a short "Use Ctrl + scroll to zoom" hint), and only Ctrl/Cmd + wheel or a trackpad pinch zooms. `allowMouseWheelZoom: true` restores the old wheel, which zooms on every scroll; `chart.zoom.wheelHint: false` hides the hint. Set `pinch: true` to force the gestures on a toolbar-less chart, or see `chart.zoom.resetControl` (v7.4) for the other way to satisfy the gate.
|
|
71
72
|
>
|
|
72
|
-
> **Premium features and licensing.** Nine features are premium: `trellis` (small multiples, 7.0), `storyboard`, `link` (crossfilter / linked views), `ink` (annotation authoring), `measure`, `context-menu`, `perspectives` (shareable views), `history` (undo/redo) and `highlight-filter` (`highlightFilter`, 7.9). Two chart types are premium: `unit` / `waffle`, and `raincloud` (7.1). These still function fully, but render an `APEXCHARTS` trial watermark until an entitled license is set via `ApexCharts.setLicense(key)` (static) or per-chart `chart.license`. They require a `premium` or `enterprise` plan; a `pro` key or the free tier keeps the watermark. Every other chart type and free module is never gated. Premium and Tier 2 are separate axes: since 8.0 every premium item is Tier 2, but not every Tier 2 item is premium (`renderer-canvas`, `drilldown`, `waterfall`, `dumbbell`, `streamgraph`, `sunburst`, `violin` and `icicle` are free and need an import). See the Licensing section in `references/feature-platform.md`.
|
|
73
|
+
> **Premium features and licensing.** Nine features are premium: `trellis` (small multiples, 7.0), `storyboard`, `link` (crossfilter / linked views), `ink` (annotation authoring), `measure`, `context-menu`, `perspectives` (shareable views), `history` (undo/redo) and `highlight-filter` (`highlightFilter`, 7.9). Two chart types are premium: `unit` / `waffle`, and `raincloud` (7.1). These still function fully, but render an `APEXCHARTS` trial watermark until an entitled license is set via `ApexCharts.setLicense(key)` (static) or per-chart `chart.license`. They require a `premium` or `enterprise` plan; a `pro` key or the free tier keeps the watermark. Every other chart type and free module is never gated. Premium and Tier 2 are separate axes: since 8.0 every premium item is Tier 2, but not every Tier 2 item is premium (`renderer-canvas`, `drilldown`, `radial-targets`, `waterfall`, `dumbbell`, `streamgraph`, `sunburst`, `violin` and `icicle` are free and need an import). See the Licensing section in `references/feature-platform.md`.
|
|
73
74
|
|
|
74
75
|
## 1. Critical Rules
|
|
75
76
|
|
|
@@ -79,22 +80,22 @@ metadata:
|
|
|
79
80
|
4. **`yaxis` must be an array** when using multiple y-axes. Each entry needs a `seriesName` to map to the correct series.
|
|
80
81
|
5. **`tooltip.shared` and `tooltip.intersect` are mutually exclusive.** `shared: true` shows all series at an x-position. `intersect: true` shows only the hovered point.
|
|
81
82
|
6. **Use `null` (not `undefined` or empty string)** for missing data points. `undefined` is silently ignored and breaks the chart.
|
|
82
|
-
7. **`chart.stacked: true`** stacks `bar`, `area` and `line` series. In a mixed chart only the bar series stack by default (`chart.stackOnlyBar` defaults to `true`); set `stackOnlyBar: false` to stack its line and area series too. `waterfall`, `dumbbell` and `streamgraph` force it off, since they do their own accumulation.
|
|
83
|
+
7. **`chart.stacked: true`** stacks `bar`, `area` and `line` series. In a mixed chart only the bar series stack by default (`chart.stackOnlyBar` defaults to `true`); set `stackOnlyBar: false` to stack its line and area series too. `waterfall`, `dumbbell` and `streamgraph` force it off, since they do their own accumulation. `chart.stackType: '100%'` draws each stack as shares of its total on a 0 to 100 axis; since v8.5 that holds for area and line stacks too (before, only bars drew percentages).
|
|
83
84
|
8. **Responsive breakpoints** must be in ascending order in the `responsive` array.
|
|
84
85
|
9. **For mixed/combo charts**, set `type` on each individual series object, not just on `chart.type`.
|
|
85
86
|
10. **RadialBar values sit on the `plotOptions.radialBar.min` to `max` domain** (default 0 to 100, so percentages by default). Set `min` / `max` to plot raw values; a value outside the domain is clamped to the end of the arc.
|
|
86
87
|
11. **Color hex values must include the `#` prefix** (e.g., `'#FF5733'`, not `'FF5733'`).
|
|
87
|
-
12. **The default `apexcharts` bundle is not everything (v8).** Next to `import ApexCharts from 'apexcharts'`, add `import 'apexcharts/unit'` (also for `waffle`), `'apexcharts/sunburst'`, `'apexcharts/violin'`, `'apexcharts/icicle'` or `'apexcharts/raincloud'` before writing that chart type. Add `import 'apexcharts/features/<name>'` before writing a `waterfall`, `dumbbell` or `streamgraph` chart, or using `drilldown`, `highlightFilter` (`highlight-filter`), `trellis`, `storyboard`, `perspectives`, `ink`, `renderer: 'canvas'` (`renderer-canvas`), `link`, `measure`, `history` or the context menu (`context-menu`). `import ApexCharts from 'apexcharts/full'` (script tag: `dist/apexcharts.full.min.js`) is the one entry that needs none of these. See the box above.
|
|
88
|
+
12. **The default `apexcharts` bundle is not everything (v8).** Next to `import ApexCharts from 'apexcharts'`, add `import 'apexcharts/unit'` (also for `waffle`), `'apexcharts/sunburst'`, `'apexcharts/violin'`, `'apexcharts/icicle'` or `'apexcharts/raincloud'` before writing that chart type. Add `import 'apexcharts/features/<name>'` before writing a `waterfall`, `dumbbell` or `streamgraph` chart, or using `drilldown`, `highlightFilter` (`highlight-filter`), `plotOptions.radialBar.targets` (`radial-targets`, v8.5), `trellis`, `storyboard`, `perspectives`, `ink`, `renderer: 'canvas'` (`renderer-canvas`), `link`, `measure`, `history` or the context menu (`context-menu`). `import ApexCharts from 'apexcharts/full'` (script tag: `dist/apexcharts.full.min.js`) is the one entry that needs none of these. See the box above.
|
|
88
89
|
13. **Tree-shaking**: importing `apexcharts/core` gives you a bare class, and you must also import chart-type entries and feature entries separately.
|
|
89
90
|
14. **First-class aliases**: `funnel` and `pyramid` render through the bar engine; `gauge` renders through radialBar. Use them as `chart.type` directly (no `plotOptions.bar.isFunnel` needed). They are covered by the `apexcharts/bar` and `apexcharts/radialBar` tree-shaking entries respectively.
|
|
90
91
|
15. **`violin` (statistical)** uses a per-point density profile: `data: [{ x, y: { density: [[value, weight], ...], points?: [number] } }]`, not a plain number. Since v6.9 a datum may instead supply only raw observations (`points: [number]`, no `y`) and the library derives the density via KDE (needs `apexcharts/features/stats` when tree-shaking).
|
|
91
|
-
16. **`render()` is idempotent**: calling `render()` twice on the same instance returns the same promise instead of building a duplicate chart. You still must `destroy()` before creating a *new* instance on the same element.
|
|
92
|
+
16. **`render()` is idempotent**: calling `render()` twice on the same instance returns the same promise instead of building a duplicate chart. You still must `destroy()` before creating a *new* instance on the same element. Since v8.1 `render()` after `destroy()` draws that instance afresh, and `updateOptions` / `updateSeries` on a destroyed chart log a warning and resolve instead of throwing.
|
|
92
93
|
17. **`histogram` (v6.9)** series carry **raw observations** (one number per event), not pre-aggregated counts; the chart chooses bin edges and counts them. Binning ships behind the stats feature: use the `apexcharts/histogram` entry, or `import 'apexcharts/features/stats'` alongside `apexcharts/bar` (the default `apexcharts` bundle already includes it).
|
|
93
94
|
18. **`waterfall` (v7.1) accumulates for you.** The series carries the **deltas**, not the running total. A row that should show the running total carries `isSubtotal` or `isTotal` and **no `y`**; the library measures it. Do not pre-compute cumulative values.
|
|
94
95
|
19. **`dumbbell` (v7.1) takes one series per measure**, each with the same `x` categories: `[{ name: '2020', data: [{ x, y }] }, { name: '2025', data: [{ x, y }] }]`. Do **not** zip the values into `y: [low, high]` pairs; that is the older `plotOptions.bar.isDumbbell` range-bar form, which still works but is a different chart.
|
|
95
96
|
20. **`raincloud` (v7.1) takes the raw sample**, one datum per category: `data: [{ x, points: [number] }]`. It is a premium Tier 2 type, so it needs `import 'apexcharts/raincloud'` on top of the default bundle.
|
|
96
|
-
21. **Unknown names fail loudly (v7.9).** An unknown `chart.type` throws when the chart is constructed or updated, and the message names the closest real type (`'column'` is valid, a synonym for `'bar'`; `''` and `null` draw a line chart). An unknown top-level option key is kept but never read. Numeric-string axis bounds such as `yaxis.min: '10'` work, and a bound that cannot be parsed is ignored (the axis scales to the data). Both cases log a console warning, except in `apexcharts.min.js`
|
|
97
|
-
22. **A script tag names the exact version shown here**: `https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
97
|
+
21. **Unknown names fail loudly (v7.9).** An unknown `chart.type` throws when the chart is constructed or updated, and the message names the closest real type (`'column'` is valid, a synonym for `'bar'`; `''` and `null` draw a line chart). An unknown top-level option key is kept but never read. Numeric-string axis bounds such as `yaxis.min: '10'` work, and a bound that cannot be parsed is ignored (the axis scales to the data). Both cases log a console warning, except in `apexcharts.min.js` (the minified script-tag file), which strips it. Since v8.1 the CommonJS builds (the `*.common.js` files `require('apexcharts')` loads) keep their warnings, and every build, `apexcharts.min.js` included, prints the warning that names a missing Tier 2 import.
|
|
98
|
+
22. **A script tag names the exact version shown here**: `https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/apexcharts.min.js` or `https://cdn.jsdelivr.net/npm/apexcharts@8.6.0/dist/apexcharts.min.js`. Never write a 3.x or 4.x URL such as `.../apexcharts/3.54.1/...`: those are releases from 2024 and early 2025, and this skill does not describe them. If the environment only accepts an older release, use the newest one it accepts with the same major version as these URLs. See `references/framework-wrappers.md` for add-on files on each CDN.
|
|
98
99
|
|
|
99
100
|
---
|
|
100
101
|
|
|
@@ -252,6 +253,7 @@ import 'apexcharts/features/waterfall' # (v7.1) waterfall chart type (Tier
|
|
|
252
253
|
import 'apexcharts/features/dumbbell' # (v7.1) dumbbell chart type (Tier 2 since v8)
|
|
253
254
|
import 'apexcharts/features/streamgraph' # (v7.1) streamgraph chart type (Tier 2 since v8)
|
|
254
255
|
import 'apexcharts/features/highlight-filter' # (v7.9) Part-of-whole highlight, highlightFilter (premium)
|
|
256
|
+
import 'apexcharts/features/radial-targets' # (v8.5) plotOptions.radialBar.targets on radialBar / gauge (free)
|
|
255
257
|
import 'apexcharts/features/trellis' # (v7.0) Small multiples (premium)
|
|
256
258
|
import 'apexcharts/features/storyboard' # Scrollytelling (premium; registers perspectives)
|
|
257
259
|
import 'apexcharts/features/perspectives' # Shareable view state (premium)
|
|
@@ -317,6 +319,8 @@ await chart.updateOptions({
|
|
|
317
319
|
chart.destroy()
|
|
318
320
|
```
|
|
319
321
|
|
|
322
|
+
**Your options object is never written into (v8.1).** The constructor and every update copy what you pass, so after `updateOptions` / `updateSeries` your own object still holds what you wrote, not the merged result. Code that read the library's defaults or a later update back from it should read the live config from `chart.w.config` (not in the shipped types, so cast in TypeScript).
|
|
323
|
+
|
|
320
324
|
---
|
|
321
325
|
|
|
322
326
|
## 5. Formatter Function Signatures
|
|
@@ -326,18 +330,20 @@ chart.destroy()
|
|
|
326
330
|
| `xaxis.labels.formatter` | `(value: string \| number, timestamp?: number, opts?) => string` | Formatted x-axis tick label |
|
|
327
331
|
| `yaxis.labels.formatter` | `(value: number, opts?) => string` | Formatted y-axis tick label |
|
|
328
332
|
| `tooltip.x.formatter` | `(value: number, opts?) => string` | Tooltip x-value text |
|
|
329
|
-
| `tooltip.y.formatter` | `(value: number \| null, opts?) => string` | Tooltip y-value text. `value` is `null` at a gap, so guard before a number method: `(val) => val == null ? 'n/a' : val.toFixed(2)` |
|
|
333
|
+
| `tooltip.y.formatter` | `(value: number \| null, opts?) => string \| null \| undefined` | Tooltip y-value text. `value` is `null` at a gap, so guard before a number method: `(val) => val == null ? 'n/a' : val.toFixed(2)`. In a shared tooltip, returning `null` or `undefined` hides that series' row (typed since v8.2) |
|
|
330
334
|
| `tooltip.y.title.formatter` | `(seriesName: string, opts?) => string` | Tooltip series title |
|
|
331
335
|
| `tooltip.z.formatter` | `(value: number) => string` | Tooltip z-value (bubble) |
|
|
332
336
|
| `dataLabels.formatter` | `(value: number \| string \| number[], opts?) => string \| number` | Data label text |
|
|
333
|
-
| `legend.formatter` | `(legendName: string, opts?) => string` | Legend item
|
|
337
|
+
| `legend.formatter` | `(legendName: string, opts?) => string` | Legend item HTML. `legendName` is the raw, unescaped name |
|
|
334
338
|
| `plotOptions.pie.donut.labels.value.formatter` | `(val: string) => string` | Donut center value |
|
|
335
339
|
| `plotOptions.pie.donut.labels.total.formatter` | `(w: { globals, config }) => string` | Donut center total |
|
|
336
340
|
| `plotOptions.radialBar.dataLabels.value.formatter` | `(val: number) => string` | RadialBar center value |
|
|
337
341
|
|
|
338
|
-
**Important:** All formatters must return a `string` (or `number` for `dataLabels.formatter`). Never return `undefined
|
|
342
|
+
**Important:** All formatters must return a `string` (or `number` for `dataLabels.formatter`). Never return `undefined`, except from `tooltip.y.formatter` in a shared tooltip, where `null` or `undefined` deliberately hides that row.
|
|
343
|
+
|
|
344
|
+
**Names are text, formatter output is HTML (v8.3.1, v8.4).** Series names, categories, goal names and treemap / sunburst / icicle node names are escaped in the legend and tooltip (and in `renderToHTML` output), so markup inside them shows literally. To style a name, return the markup from `legend.formatter` or a tooltip formatter: a result that differs from the name is written as HTML, one that hands the name back unchanged is shown as text. Those formatters receive the raw name, so escape it yourself (`&` and `<`) before wrapping it in markup when names come from user data.
|
|
339
345
|
|
|
340
|
-
**Per-point data label offsets (v6.8):** `dataLabels.offsetX` and `dataLabels.offsetY` accept `number | ((opts) => number)`. The function receives `{ series, seriesIndex, dataPointIndex, w }` (same signature as `dataLabels.style.colors` functions). Use it for deliberate placement; keep it pure, since it may be called more than once per label. Collisions do not need it: since v7.8 `dataLabels.avoidOverlap` (on by default) nudges labels that land on each other apart along the value axis, across series as well as within one, after the offsets are applied (radial types keep their own placement). Tune it with `{ gap, maxShift, hide }`, or set `avoidOverlap: false` to keep each label exactly at its mark and offset.
|
|
346
|
+
**Per-point data label offsets (v6.8):** `dataLabels.offsetX` and `dataLabels.offsetY` accept `number | ((opts) => number)`. The function receives `{ series, seriesIndex, dataPointIndex, w }` (same signature as `dataLabels.style.colors` functions). Use it for deliberate placement; keep it pure, since it may be called more than once per label. Collisions do not need it: since v7.8 `dataLabels.avoidOverlap` (on by default) nudges labels that land on each other apart along the value axis, across series as well as within one, after the offsets are applied (radial types keep their own placement). Tune it with `{ gap, maxShift, hide, hideOrder }`, or set `avoidOverlap: false` to keep each label exactly at its mark and offset. *(v8.5)* `maxShift: 0` never moves a label, and `hideOrder: 'balanced'` spreads the labels `hide` drops across the series instead of emptying the later-drawn one (default `'later'`). On a line or area chart, where a moved label sits beside the wrong value, prefer `{ maxShift: 0, hide: true, hideOrder: 'balanced' }`.
|
|
341
347
|
|
|
342
348
|
---
|
|
343
349
|
|
|
@@ -431,7 +437,7 @@ Also: do NOT use `xaxis.categories` when your data already has `{ x, y }` format
|
|
|
431
437
|
|
|
432
438
|
### Pitfall 6: tooltip.shared vs tooltip.intersect
|
|
433
439
|
|
|
434
|
-
❌ **WRONG
|
|
440
|
+
❌ **WRONG**: both enabled (conflicting; constructing the chart throws, and an `updateOptions` that sets both logs a warning):
|
|
435
441
|
```js
|
|
436
442
|
{ tooltip: { shared: true, intersect: true } }
|
|
437
443
|
```
|
|
@@ -441,10 +447,13 @@ Also: do NOT use `xaxis.categories` when your data already has `{ x, y }` format
|
|
|
441
447
|
// Mode A: Show all series values at x-position (default for line/area)
|
|
442
448
|
{ tooltip: { shared: true, intersect: false } }
|
|
443
449
|
|
|
444
|
-
// Mode B: Show only hovered data point (better for scatter)
|
|
450
|
+
// Mode B: Show only hovered data point (better for scatter). Since v8.7, where
|
|
451
|
+
// several series' markers are drawn at the hovered spot, it lists one row per series.
|
|
445
452
|
{ tooltip: { shared: false, intersect: true } }
|
|
446
453
|
```
|
|
447
454
|
|
|
455
|
+
**Hover without the tooltip box *(v8.5)***: `tooltip.visible: false` keeps everything a hover resolves (the `mouseMove` / `click` / data point events still report the point, crosshairs and hover markers still follow their own options) and draws no tooltip box, for an app that shows hover details in its own UI. `tooltip.enabled: false` turns hover handling off entirely.
|
|
456
|
+
|
|
448
457
|
**Reaching content inside a `custom` tooltip *(v7.6)***: a tooltip closes as the pointer leaves the data point, so a link or button returned by `custom` can never be clicked. `tooltip.interactive: true` holds it open while the pointer is over it. It is off by default, and while it is on `followCursor` is **ignored** (a tooltip that trails the cursor retreats from every approach); the configured `followCursor` value is left alone and applies again the moment `interactive` goes back off.
|
|
449
458
|
|
|
450
459
|
```js
|
|
@@ -595,7 +604,7 @@ The console names the import in every case (since 7.9.1 the minified bundle prin
|
|
|
595
604
|
|
|
596
605
|
- **A Tier 2 chart type** (`unit`, `waffle`, `sunburst`, `violin`, `icicle`, and `raincloud`, which draws through violin): `render()` rejects and nothing draws. An `updateOptions`, `updateSeries` or `appendSeries` that asks for one is refused, and the chart stays as it was.
|
|
597
606
|
- **`waterfall`, `dumbbell` or `streamgraph`** without its feature (or a `raincloud` on a page that has violin but not the raincloud feature): one warning and an empty plot.
|
|
598
|
-
- **A Tier 2 feature** (`drilldown`, `highlightFilter`, `trellis`, `storyboard`, `perspectives`, `ink`, `renderer: 'canvas'`, `link`, `measure`, `history`, `contextMenu`): the chart draws without it, with a warning when its config is present. A trellis renders as one plain chart; a drilldown chart draws its root level and never navigates, and `chart.drillDown()` throws.
|
|
607
|
+
- **A Tier 2 feature** (`drilldown`, `highlightFilter`, `plotOptions.radialBar.targets`, `trellis`, `storyboard`, `perspectives`, `ink`, `renderer: 'canvas'`, `link`, `measure`, `history`, `contextMenu`): the chart draws without it, with a warning when its config is present. A trellis renders as one plain chart; a drilldown chart draws its root level and never navigates, and `chart.drillDown()` throws; a radialBar or gauge draws its dial without the targets.
|
|
599
608
|
|
|
600
609
|
Or start from `import ApexCharts from 'apexcharts/full'`, which needs none of these.
|
|
601
610
|
|
|
@@ -664,6 +673,7 @@ await chart.updateOptions({ title: { text: 'New Title' } })
|
|
|
664
673
|
| `setLocale(localeName)` | Switch locale. |
|
|
665
674
|
| `toggleDataPointSelection(seriesIndex, dataPointIndex?)` | Select/deselect data point. |
|
|
666
675
|
| `rowSeries(opts?)` | *(v6.9)* Returns the raw rows behind this chart's marks as a unit-chart series (one cluster per mark), or `null` when the type has no row source (works for histogram / boxPlot / violin, needs `apexcharts/features/stats`). `opts.maxRows` caps the output (default 3000). Drawing the result needs the `unit` type, Tier 2 since v8 (`import 'apexcharts/unit'`). |
|
|
676
|
+
| `getRadialScales()` | *(v8.5)* Where a radialBar or gauge drew its dial on the last render: `{ cx, cy, startAngle, endAngle, min, max, radius, thickness, rings, bands, hollow, needle, angle(v), point(v, r?) }`, in the px of `getChartArea()`. `null` on other types and before the first render. Core, no import. |
|
|
667
677
|
| `getState()` | Returns snapshot of chart state. |
|
|
668
678
|
| `addEventListener(name, handler)` | Subscribe to chart event. |
|
|
669
679
|
| `removeEventListener(name, handler)` | Unsubscribe from chart event. |
|
|
@@ -736,6 +746,12 @@ await chart.updateOptions({ title: { text: 'New Title' } })
|
|
|
736
746
|
markerClick: (event, chart, options) => {},
|
|
737
747
|
xAxisLabelClick: (event, chart, options) => {},
|
|
738
748
|
|
|
749
|
+
// (v8.7) On a marker (line, area, scatter, bubble, radar), markerClick, dataPointSelection
|
|
750
|
+
// and the SVG renderer's click carry options.coincident (ApexCoincidentPoint[]: { seriesIndex, dataPointIndex })
|
|
751
|
+
// for every visible series whose marker is drawn at that spot. options.seriesIndex /
|
|
752
|
+
// dataPointIndex still name the marker on top. The canvas renderer's click has no
|
|
753
|
+
// coincident; use markerClick there.
|
|
754
|
+
|
|
739
755
|
// Data point events
|
|
740
756
|
dataPointSelection: (event, chart, options) => {},
|
|
741
757
|
dataPointMouseEnter: (event, chart, options) => {},
|
|
@@ -773,7 +789,7 @@ Every feature below is off by default in config terms. The **Tier** column is ab
|
|
|
773
789
|
|
|
774
790
|
| Feature | Tier | Import | One-liner |
|
|
775
791
|
|---|---|---|---|
|
|
776
|
-
| **Weave** (plugins) | 1 | `apexcharts/features/weave` | Publish reusable chart plugins against a stable `ApexCharts.registerPlugin({ name, setup })` API; activate per chart with `plugins: [{ name }]`. Contract is at **
|
|
792
|
+
| **Weave** (plugins) | 1 | `apexcharts/features/weave` | Publish reusable chart plugins against a stable `ApexCharts.registerPlugin({ name, setup })` API; activate per chart with `plugins: [{ name }]`. Contract is at **v7** (v8.1): `info`/`categories`/`markDerived` (v2), `reserve` (v3), `pointer` (v4), `claim`/`drawn`/`declare`/`can` (v6), `highlight()` (v7), and the capabilities `observations` and `scale-orientation` (8.0.1) and `radial-scales` (8.5). Declare the **lowest** `apiVersion` you can run on and feature-detect the rest: a host older than the version you declare skips your plugin outright. |
|
|
777
793
|
| **Marks** (custom series) | 1 | `apexcharts/features/marks` | `ApexCharts.registerSeriesType(name, { renderItem })` for first-class custom marks (lollipop, bullet). Baseline is `scales.y(0)`, **not** `api.zeroY`. |
|
|
778
794
|
| **Facet** (themes/tokens) | 1 | `apexcharts/features/facet` | `theme: { follow: 'os', name }`, `--apx-*` CSS custom props, `ApexCharts.registerTheme`. |
|
|
779
795
|
| **Morph** | 1 | `apexcharts/features/morph` | Animated transitions between chart types. |
|
|
@@ -784,6 +800,7 @@ Every feature below is off by default in config terms. The **Tier** column is ab
|
|
|
784
800
|
| **Marker batching** | core | none | *(v7.0)* `markers: { largeDatasetThreshold: n }`. Above `n` points, a series' markers are drawn as one path per marker size instead of one element per point. **Opt-in, default `0` (off)**, because merged marker paths are not pixel-identical: overlapping markers lose their individual outlines and dense clusters read flatter. Also covers the markers `showNullDataPoints` adds, which is what makes a null-heavy series slow even at `size: 0`. |
|
|
785
801
|
| **Drilldown** | **2** | `apexcharts/features/drilldown` | *(Tier 2 since v8.0)* `drilldown: { enabled, series }` + a `drilldown` id on data points; `chart.drillDown()/drillUp()`. v6.9 adds line/area support, async levels (`onDrillDown` may return a Promise), a loading overlay, and the `drillDownError` event. |
|
|
786
802
|
| **Highlight filter** | **2** | `apexcharts/features/highlight-filter` | *(v7.9, premium)* `highlightFilter` draws each value faded with a part of it solid in front, from the same baseline. The part travels with the data: `series[].highlightData` (parallel to `data`) or `{ x, y, highlight }` per point, `highlightFilter.data` on pie / donut / polarArea / radialBar; `chart.highlightFilter.set(parts)` / `clear()`. Bar, column, funnel, line, area, pie, donut, polarArea, radialBar (and gauge), treemap. See "Highlight filter" in `references/feature-platform.md`. |
|
|
803
|
+
| **Radial targets** | **2** | `apexcharts/features/radial-targets` | *(v8.5, free)* `plotOptions.radialBar.targets: [{ value, seriesIndex?, shape?, position?, label? }]` marks a target or limit on a radialBar ring or a gauge (`value: 'series'` follows the ring's own value). Without the import the dial draws without them and the console warns once. See `references/circular-charts.md`. |
|
|
787
804
|
| **Trellis** (small multiples) | **2** | `apexcharts/features/trellis` | *(v7.0, premium)* `trellis: { by: 'region', minPanelWidth }` splits the series into a grid of real charts sharing one scale, legend, toolbar and crosshair. Also `row` × `column` for 2-D grids. |
|
|
788
805
|
| **Strata** (canvas) | **2** | `apexcharts/features/renderer-canvas` | `chart: { renderer: 'auto', rendererThreshold }` paints the dense series layer to canvas while axes/tooltips/exports stay SVG. Falls back to SVG if the module is missing. |
|
|
789
806
|
| **Rewind** (undo/redo) | **2** | `apexcharts/features/history` | *(premium)* `chart: { history: { enabled: true } }`, then `chart.history.undo()/redo()/jump()/transaction()`. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apexcharts-skill",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "AI coding skill for ApexCharts.js — structured reference docs that help AI assistants (Claude, Cursor, Copilot, etc.) generate correct ApexCharts code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"apexcharts",
|
package/references/bar-charts.md
CHANGED
|
@@ -72,8 +72,7 @@ import ApexCharts from 'apexcharts/dumbbell' // == apexcharts/bar + features/d
|
|
|
72
72
|
|
|
73
73
|
```js
|
|
74
74
|
{
|
|
75
|
-
chart: { type: 'bar', height: 350, stacked: true },
|
|
76
|
-
// stackType: '100%' // uncomment for percentage stacking
|
|
75
|
+
chart: { type: 'bar', height: 350, stacked: true }, // add stackType: '100%' to chart for percentage stacking
|
|
77
76
|
series: [
|
|
78
77
|
{ name: 'Product A', data: [44, 55, 41] },
|
|
79
78
|
{ name: 'Product B', data: [13, 23, 20] },
|
|
@@ -84,6 +83,8 @@ import ApexCharts from 'apexcharts/dumbbell' // == apexcharts/bar + features/d
|
|
|
84
83
|
}
|
|
85
84
|
```
|
|
86
85
|
|
|
86
|
+
`chart.stackType: '100%'` draws each stack as shares of its total on a 0 to 100 axis, and labels read as percentages; the tooltip keeps the raw value. Since v8.5 the same holds for stacked area and line series (before, they drew raw values on the 0 to 100 axis). In a combo, a line or area joins the percent stack only with `chart.stackOnlyBar: false`.
|
|
87
|
+
|
|
87
88
|
### Range Bar (start/end values)
|
|
88
89
|
|
|
89
90
|
```js
|
|
@@ -101,6 +102,8 @@ import ApexCharts from 'apexcharts/dumbbell' // == apexcharts/bar + features/d
|
|
|
101
102
|
}
|
|
102
103
|
```
|
|
103
104
|
|
|
105
|
+
Data labels are off by default on a range bar, and once enabled the default prints `end - start`. A `dataLabels.formatter` of your own receives the value as `[start, end]`, on vertical range columns as well since v8.2 (before, those passed only the end): `` formatter: ([start, end]) => `${start} to ${end}` ``.
|
|
106
|
+
|
|
104
107
|
### Timeline / Gantt Chart (Range Bar with dates)
|
|
105
108
|
|
|
106
109
|
```js
|
|
@@ -341,7 +344,7 @@ A stack of a single data point also stopped rounding its baseline in v7.4, which
|
|
|
341
344
|
dataLabels: { animate: { enabled: false } }
|
|
342
345
|
```
|
|
343
346
|
|
|
344
|
-
**⚠️ `dataLabels.avoidOverlap` is on by default (v7.8).** Labels that land on each other, across series too, are nudged apart along the value axis (left and right on a horizontal bar), each by at most about its own size. A pair that cannot be separated stays overlapping unless you pass `{ hide: true }`. Tune it with `{ gap, maxShift, hide }`, or set `false` to keep every label where it was placed. Rotated labels (`orientation: 'vertical'`) are never moved. A manual `offsetY` that only separated labels may no longer be needed.
|
|
347
|
+
**⚠️ `dataLabels.avoidOverlap` is on by default (v7.8).** Labels that land on each other, across series too, are nudged apart along the value axis (left and right on a horizontal bar), each by at most about its own size. A pair that cannot be separated stays overlapping unless you pass `{ hide: true }`. Tune it with `{ gap, maxShift, hide }`, or set `false` to keep every label where it was placed. Rotated labels (`orientation: 'vertical'`) are never moved. A manual `offsetY` that only separated labels may no longer be needed. *(v8.5)* `maxShift: 0` never moves a label, and `hideOrder: 'balanced'` makes `hide` drop labels evenly across the series rather than always the later-drawn one (default `'later'`).
|
|
345
348
|
|
|
346
349
|
### Bar Chart Race (v6.4)
|
|
347
350
|
|
|
@@ -448,3 +451,4 @@ Bar, column, funnel and pyramid charts take `highlightFilter`, which draws each
|
|
|
448
451
|
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'`.
|
|
449
452
|
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.
|
|
450
453
|
13. **Waterfall or dumbbell on the default bundle** *(v8.0)*: draws an empty plot plus one console warning. Add `import 'apexcharts/features/waterfall'` (or `'apexcharts/features/dumbbell'`) next to `import ApexCharts from 'apexcharts'`.
|
|
454
|
+
14. **Expecting every category name on a dense horizontal bar chart** *(v8.5)*: names that would overlap are thinned (the top one always stays, the rest evenly spaced; the tooltip and keyboard navigation keep every name). `xaxis.labels.hideOverlappingLabels: false` draws them all, and so does setting a `yaxis.labels.formatter`.
|
|
@@ -79,6 +79,8 @@ Use `null` to create gaps in the line:
|
|
|
79
79
|
series: [{ data: [10, 25, null, null, 50, 60] }]
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
In `{ x, y }` data write a gap as `{ x, y: null }`, which keeps its category label. Since v8.1 a bare `null` entry in `{ x, y }` or `[x, y]` data also draws as a gap instead of throwing, but it blanks the category label at that slot, and one among the first three points logs a "mixed formats" console warning.
|
|
83
|
+
|
|
82
84
|
### Scatter Chart
|
|
83
85
|
|
|
84
86
|
Always use XY format:
|
|
@@ -202,6 +204,17 @@ stroke: {
|
|
|
202
204
|
}
|
|
203
205
|
```
|
|
204
206
|
|
|
207
|
+
**Dash patterns (v8.5).** Every dash option (`stroke.dashArray`, `markers.strokeDashArray`, `grid.strokeDashArray`, annotation `strokeDashArray`, `forecastDataPoints.dashArray`, crosshair strokes) takes a number (dash and gap of that length), a pattern string (`'8 3 2 3'` or `'8,3,2,3'`) or an array of lengths (type `ApexDashPattern`). On the per-series options a **top-level array is one value per series**, so:
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
stroke: { dashArray: '8 3 2 3' } // dash-dot on every series
|
|
211
|
+
stroke: { dashArray: [0, '8 3 2 3'] } // first solid, second dash-dot
|
|
212
|
+
stroke: { dashArray: [8, 3, 2, 3] } // NOT a pattern: four series dashed 8, 3, 2 and 3
|
|
213
|
+
stroke: { dashArray: [0, [8, 3, 2, 3]] } // a nested array is a pattern for one series
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Dotted lines are a zero-length dash with a round cap: `dashArray: '0 6'` with `stroke.lineCap: 'round'`. X and y axis annotations take `strokeLineCap: 'butt' | 'square' | 'round'` *(v8.5, default `'butt'`)* for the same effect on their lines and range borders.
|
|
217
|
+
|
|
205
218
|
### Markers
|
|
206
219
|
|
|
207
220
|
```js
|
|
@@ -256,6 +269,22 @@ xaxis: {
|
|
|
256
269
|
}
|
|
257
270
|
```
|
|
258
271
|
|
|
272
|
+
### Mouse-wheel zoom is cooperative (v8.3)
|
|
273
|
+
|
|
274
|
+
With `chart.zoom.enabled` and the default `allowMouseWheelZoom: 'auto'` (offered only where the toolbar reset button is present), a bare wheel over the chart scrolls the page and briefly shows a hint; **Ctrl/Cmd + wheel**, or a trackpad pinch, zooms. Charts written for the pre-8.3 wheel no longer zoom on a plain scroll.
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
chart: {
|
|
278
|
+
zoom: {
|
|
279
|
+
enabled: true,
|
|
280
|
+
allowMouseWheelZoom: true, // every wheel zooms again (even with the toolbar hidden)
|
|
281
|
+
wheelHint: false, // or keep 'auto' and hide the hint
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The hint text is the locale's `toolbar.wheelZoomHint` (`chart.locales[].options.toolbar.wheelZoomHint`, default `'Use {key} + scroll to zoom'`, `{key}` becomes Ctrl or ⌘), translated in every shipped locale.
|
|
287
|
+
|
|
259
288
|
### A way out of a zoom when the toolbar is hidden (v7.4)
|
|
260
289
|
|
|
261
290
|
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.
|
|
@@ -34,7 +34,7 @@ import { person, registerMarks } from 'apexcharts/pictograms'
|
|
|
34
34
|
// Pictogram glyph collection (v7.0), one drawn mark per unit. See "Pictograms" below.
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
**⚠️ Sunburst and unit / waffle are Tier 2 since v8.0.** Pie, donut, polarArea, radialBar and gauge are in the default `apexcharts` bundle; `sunburst` and `unit` (with the `waffle` alias and the beeswarm layout) are not. Add `import 'apexcharts/sunburst'` or `import 'apexcharts/unit'` next to `import ApexCharts from 'apexcharts'` (script tag: `dist/sunburst.js` or `dist/unit.js`), or use the full bundle (`apexcharts/full`, `dist/apexcharts.full.min.js`). Without it the chart draws nothing and the console says the type is not registered, naming the import.
|
|
37
|
+
**⚠️ Sunburst and unit / waffle are Tier 2 since v8.0.** Pie, donut, polarArea, radialBar and gauge are in the default `apexcharts` bundle; `sunburst` and `unit` (with the `waffle` alias and the beeswarm layout) are not. Add `import 'apexcharts/sunburst'` or `import 'apexcharts/unit'` next to `import ApexCharts from 'apexcharts'` (script tag: `dist/sunburst.js` or `dist/unit.js`), or use the full bundle (`apexcharts/full`, `dist/apexcharts.full.min.js`). Without it the chart draws nothing and the console says the type is not registered, naming the import. `plotOptions.radialBar.targets` (v8.5) is a Tier 2 feature as well: `import 'apexcharts/features/radial-targets'` (see "Targets" below).
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
@@ -93,7 +93,7 @@ A gauge is a single-value `radialBar` alias. Series is a flat one-element array;
|
|
|
93
93
|
{ from: 30, to: 70, color: '#FEB019' },
|
|
94
94
|
{ from: 70, to: 100, color: '#00E396' }
|
|
95
95
|
],
|
|
96
|
-
bandsStyle: { strokeWidth: '50%', gap:
|
|
96
|
+
bandsStyle: { strokeWidth: '50%', gap: 2 }, // gap: px along the band (v8.1); '1%' of the scale or '1.5deg' (v8.5) look the same at every size
|
|
97
97
|
ticks: {
|
|
98
98
|
show: true,
|
|
99
99
|
major: { count: 11, length: 8, width: 2, color: '#334155', placement: 'outside' },
|
|
@@ -110,6 +110,53 @@ A gauge is a single-value `radialBar` alias. Series is a flat one-element array;
|
|
|
110
110
|
|
|
111
111
|
A plain radialBar is effectively a gauge with `shape: 'arc'`. A semi-circle gauge is `startAngle: -90, endAngle: 90`.
|
|
112
112
|
|
|
113
|
+
**Band gaps (v8.1, v8.5):** `bandsStyle.gap` is measured in px along the band since 8.1, as documented; before that it was applied in value units, so a gap tuned on an older release may need raising. A number or `'4px'` is px, so it takes a smaller angle on a larger gauge; `'1%'` (a share of the `min..max` scale) and `'1.5deg'` look the same at every size. A band narrower than its gap is not drawn, and the console says which. Default `0`.
|
|
114
|
+
|
|
115
|
+
**Centre value label:** the default radialBar and gauge value and total formatters append `%` only on the default 0 to 100 domain *(v8.1)*; with a custom `min` / `max` (a speedometer) they print the bare value.
|
|
116
|
+
|
|
117
|
+
#### Targets (v8.5, add-on)
|
|
118
|
+
|
|
119
|
+
`plotOptions.radialBar.targets` puts marks at a value on a ring: a target, a limit, last period's reading. It needs `import 'apexcharts/features/radial-targets'` (script tag `dist/features/radial-targets.js`, or the full bundle): the add-on is free but not in the default bundle, and without it the dial draws without the targets and the console warns once.
|
|
120
|
+
|
|
121
|
+
```js
|
|
122
|
+
import ApexCharts from 'apexcharts'
|
|
123
|
+
import 'apexcharts/features/radial-targets' // Tier 2: not in the default bundle
|
|
124
|
+
|
|
125
|
+
{
|
|
126
|
+
chart: { type: 'gauge', height: 360 },
|
|
127
|
+
series: [62],
|
|
128
|
+
labels: ['Uptime'],
|
|
129
|
+
plotOptions: {
|
|
130
|
+
radialBar: {
|
|
131
|
+
min: 0, max: 100,
|
|
132
|
+
targets: [
|
|
133
|
+
{ value: 80, label: { text: 'Goal' } }, // a line across the ring
|
|
134
|
+
{ value: 'series', shape: 'triangle', position: 'outside' }, // a pointer that follows the value
|
|
135
|
+
{ value: 95, seriesIndex: 0, shape: 'circle', color: '#FF4560', id: 'limit' },
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Each entry (`ApexRadialTarget`):
|
|
143
|
+
|
|
144
|
+
| Key | Default | Notes |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `value` | required | A number in the `min..max` domain (clamped to it), or `'series'` to follow the ring's own value. A missing or non-numeric value draws nothing. |
|
|
147
|
+
| `seriesIndex` | `0` | The ring it marks. |
|
|
148
|
+
| `shape` | `'line'` | `'line'`, `'triangle'` (points at the ring) or `'circle'`. |
|
|
149
|
+
| `position` | `'across'` (`'outside'` for a triangle) | Across the ring's centre line, or off its outer or inner edge (`'inside'`). |
|
|
150
|
+
| `length` | `'130%'` for a line, `10` otherwise | Along the radius: px, or a percentage of the ring's thickness. |
|
|
151
|
+
| `width` | `3` for a line, `12` for a triangle | Across the radius, in px. Not used by a circle. |
|
|
152
|
+
| `color` / `strokeColor` / `strokeWidth` | `chart.foreColor` / none / `0` | The outline reads a mark over a band of its own colour. |
|
|
153
|
+
| `label` | none | `{ text, offset (4), style: { fontSize, fontFamily, fontWeight, color } }`, drawn upright off the mark's outer end (inner end for `'inside'`). |
|
|
154
|
+
| `cssClass`, `id` | none | `id` keeps a target's identity across updates, so a reordered list moves rather than swaps. |
|
|
155
|
+
|
|
156
|
+
Targets sit over the rings and bands, sweep in with their ring on mount, move from the old value on an update (`updateOptions` changes them), and hide with a legend-hidden ring.
|
|
157
|
+
|
|
158
|
+
**Reading the dial (v8.5, core):** `chart.getRadialScales()` returns where the last render drew it: `{ cx, cy, startAngle, endAngle, min, max, outerRadius, radius, thickness, rings: [{ seriesIndex, radius, thickness, trackThickness }], bands, hollow, needle, angle(value), point(value, radius?) }`, in the px of `chart.getChartArea()`, angles in degrees clockwise from 12 o'clock. It is frozen and replaced on every render, so read it again after an update or resize. `null` on other chart types and before the first render. A Weave plugin gets the same object as `api.radialScales`.
|
|
159
|
+
|
|
113
160
|
**Needle value label (v7.9):** on a `gauge` with `shape: 'needle'` and no `plotOptions.radialBar.dataLabels.value.offsetY`, the value is placed below the farthest reach of the needle, so the two never cross (it used to sit under the needle). Set `offsetY` to place it yourself.
|
|
114
161
|
|
|
115
162
|
### Sunburst (v6.7)
|
|
@@ -159,6 +206,8 @@ import 'apexcharts/sunburst' // Tier 2 since v8.0: not in the default bundle
|
|
|
159
206
|
|
|
160
207
|
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.
|
|
161
208
|
|
|
209
|
+
**`tooltip.custom` on a sunburst (v8.4)** runs once per hovered node with `{ seriesIndex: 0, dataPointIndex: -1, node, percentOfParent, percentOfTotal, series, w, ctx }` (`node` carries `name`, `value` and, on a branch, `children`; the percentages are 0 to 100 with one decimal). Return markup or an Element to replace the tooltip, or `null` / `undefined` to keep the built-in row. A custom written for axis data points must return `null` when `node` is set. The icicle and nested-treemap branches are called the same way (see `references/grid-charts.md`).
|
|
210
|
+
|
|
162
211
|
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.
|
|
163
212
|
|
|
164
213
|
**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`.
|
|
@@ -194,6 +243,8 @@ import 'apexcharts/unit' // Tier 2 since v8.0: not in the default bundle
|
|
|
194
243
|
|
|
195
244
|
**Motion (v6.9):** marks travel on a damped spring by default, so an update landing mid-flight retargets with the marks' velocity instead of restarting them (a dragged slider reads as continuous motion, not stutter). Configure via `plotOptions.unit.gather`: `motion: 'auto' | 'spring' | 'tween'`, `spring: 'crisp' | 'gentle' | 'snappy'`, `easing: 'outCubic' | 'inOutCubic' | 'outBack'` (setting `easing` implies tween), and `enter: 'burst' | 'fade' | 'rise'`.
|
|
196
245
|
|
|
246
|
+
**Update timing (v8.6):** a unit update follows `chart.animations.dynamicAnimation` like every other type: 350 ms by default (it was 800 ms before 8.6, ignoring that option), the springs and stagger scaled to it, and no tween at all when `dynamicAnimation.enabled` is `false`. Set `chart: { animations: { dynamicAnimation: { speed: 800 } } }` for the old pace. The first draw keeps `chart.animations.speed`.
|
|
247
|
+
|
|
197
248
|
### Unit shapes (`apexcharts/unit-shapes`, v6.10)
|
|
198
249
|
|
|
199
250
|
A companion kit of **39 shapes** a count can take (a heart, a house, a globe, the figure 1,024 drawn in 1,024 dots). Each shape is a plain callable layout, so it plugs straight into `plotOptions.unit.positions` with `layout: 'custom'`; no registration step. The entry point is tree-shaken per shape (about 4 KB gzipped each). Dots are packed to fill the outline, so one shape serves 40 dots in a sparkline and 3,000 in a poster.
|
|
@@ -509,3 +560,5 @@ Pie, donut, polarArea, radialBar and gauge charts take `highlightFilter`, which
|
|
|
509
560
|
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.
|
|
510
561
|
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.
|
|
511
562
|
16. **Sunburst, unit or waffle on the default bundle** *(v8.0)*: draws nothing and the console says the type is not registered. Add `import 'apexcharts/sunburst'` or `import 'apexcharts/unit'` next to `import ApexCharts from 'apexcharts'`. `apexcharts/unit-shapes` and `apexcharts/pictograms` do not register the unit type.
|
|
563
|
+
17. **`plotOptions.radialBar.targets` on the default bundle** *(v8.5)*: the dial draws without them and the console warns once, naming the import. Add `import 'apexcharts/features/radial-targets'` (script tag `dist/features/radial-targets.js`), or use the full bundle.
|
|
564
|
+
18. **Reading the dial geometry out of the SVG**: since v8.5 `chart.getRadialScales()` returns the centre, ring radii, angles and a value-to-angle mapping for a radialBar or gauge. Read it again after each render; the object is replaced.
|
|
@@ -8,7 +8,7 @@ Whether you need an import depends on the feature's or chart type's **tier**. Th
|
|
|
8
8
|
|
|
9
9
|
- **Tier 1** is in the default `import ApexCharts from 'apexcharts'` bundle: `exports`, `legend`, `toolbar`, `annotations`, `keyboard`, `morph`, `weave`, `marks`, `facet`, `stats`. Import these only if you started from `apexcharts/core` or a per-type entry.
|
|
10
10
|
- **Tier 2 is not in the default bundle.** Each item needs its own import next to it (or its script tag), or the full bundle:
|
|
11
|
-
- features, `import 'apexcharts/features/<name>'` (script tag `dist/features/<name>.js`): `trellis`, `storyboard`, `perspectives`, `ink`, `renderer-canvas`, `link`, `measure`, `history`, `context-menu`, `highlight-filter` *(7.9)*,
|
|
11
|
+
- features, `import 'apexcharts/features/<name>'` (script tag `dist/features/<name>.js`): `trellis`, `storyboard`, `perspectives`, `ink`, `renderer-canvas`, `link`, `measure`, `history`, `context-menu`, `highlight-filter` *(7.9)*, since 8.0 `drilldown`, `waterfall`, `dumbbell` and `streamgraph` (those three are chart types whose renderers, rangeBar and rangeArea, are in the default bundle, so next to it you add only the feature), and `radial-targets` *(8.5)*;
|
|
12
12
|
- chart types: `unit` / `waffle` (`apexcharts/unit`, `dist/unit.js`), `sunburst`, `violin`, `icicle` (`apexcharts/<type>`, `dist/<type>.js`) and `raincloud` (`apexcharts/raincloud`; script tags `dist/violin.js`, then `dist/features/raincloud.js`).
|
|
13
13
|
- **The full bundle**, `import ApexCharts from 'apexcharts/full'` (script tag `dist/apexcharts.full.min.js`, new in 8.0), has every chart type and feature and needs no add-on import. Premium items still watermark there.
|
|
14
14
|
|
|
@@ -21,7 +21,7 @@ import 'apexcharts/features/trellis' // Tier 2: not in the default bundle
|
|
|
21
21
|
<script src=".../dist/features/trellis.js"></script>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
Nothing fails silently, and since 7.9.1 the minified bundle prints these warnings too. A Tier 2 chart type that is not loaded makes `render()` reject, and the console names the import. A Tier 2 feature warns when its configuration is present but the module is not, naming the import, the script-tag file and `apexcharts.full.min.js`. Where the chart can still draw something sensible it does and says what it did: a trellis renders as a single chart, `renderer: 'canvas'` falls back to SVG, a drilldown chart draws its root level. `waterfall`, `dumbbell` and `streamgraph` without their feature draw an empty plot with one warning. `apexcharts/features/all` is the **Tier 1** set and is not a shortcut past this; the full bundle is.
|
|
24
|
+
Nothing fails silently, and since 7.9.1 the minified bundle prints these warnings too. A Tier 2 chart type that is not loaded makes `render()` reject, and the console names the import. A Tier 2 feature warns when its configuration is present but the module is not, naming the import, the script-tag file and `apexcharts.full.min.js`. Where the chart can still draw something sensible it does and says what it did: a trellis renders as a single chart, `renderer: 'canvas'` falls back to SVG, a drilldown chart draws its root level, a radialBar or gauge draws without its targets. `waterfall`, `dumbbell` and `streamgraph` without their feature draw an empty plot with one warning. `apexcharts/features/all` is the **Tier 1** set and is not a shortcut past this; the full bundle is.
|
|
25
25
|
|
|
26
26
|
Why: 24% of the 6.10.0 default bundle was licence-gated premium code that an unlicensed user could only run watermarked, and everybody downloaded it. The default bundle went 291,654 B gzipped (6.10.0) to 252,005 B (7.0.0), and 264,326 B in 7.1.0 with the three new free chart types. At 8.0.0 it is 263,188 B, and the full bundle 381,135 B (the upstream build report's figures, gzip at the default level; they move every release). See `references/tree-shaking.md` for the full tier table and per-module sizes.
|
|
27
27
|
|
|
@@ -37,12 +37,16 @@ Carried over from v6, both respecting `prefers-reduced-motion`:
|
|
|
37
37
|
1. **Coherent variable-length data transitions**: updates that add/remove data points animate as one coordinated motion instead of popping. Appended bars grow from the baseline, removed bars shrink and fade, line/area fills reshape over the union of old and new points, and markers/bubbles/axis labels ride along. Scatter and bubble now animate on dynamic updates for the first time. Disable per chart with `chart.animations.dynamicAnimation.enabled: false`; auto-skipped above `chart.animations.largeDatasetThreshold` (default 1000) and under `prefers-reduced-motion`.
|
|
38
38
|
2. **Native-feeling mobile gestures**: two-finger pinch-zoom, two-finger pan, and kinetic inertia after a flick, with axis rails so a vertical swipe still scrolls the page. Configure via `chart.zoom.pinch` (default `'auto'`) and `chart.pan.inertia` (default `true`, `friction` default `0.92`). **`'auto'` is not the same as `true`**: it enables pinch only where the toolbar reset button is present, so a zoom is always undoable. A chart with `toolbar: { show: false }` gets no pinch zoom until `pinch: true` forces it. `chart.zoom.allowMouseWheelZoom` is gated the same way, and `chart.zoom.resetControl` (v7.4) is the other half of that bargain.
|
|
39
39
|
|
|
40
|
+
**The mouse wheel is cooperative (v8.3).** Where the `'auto'` wheel is offered, a bare wheel scrolls the page past the chart and briefly shows a hint (the locale's `toolbar.wheelZoomHint`, default `'Use {key} + scroll to zoom'`, where `{key}` becomes Ctrl or ⌘); Ctrl/Cmd + wheel, or a trackpad pinch, zooms. `chart.zoom.wheelHint: false` hides the hint, and `allowMouseWheelZoom: true` restores the old wheel, which zooms on every scroll, toolbar or not. A page of zoomable charts therefore scrolls normally by default.
|
|
41
|
+
|
|
40
42
|
Also new by default: **`render()` is idempotent**: a repeated `render()` (e.g. a framework double-invoking an effect) returns the same promise instead of building a duplicate chart. `destroy()` clears it so an instance can render fresh.
|
|
41
43
|
|
|
42
|
-
|
|
44
|
+
Update behaviors worth knowing:
|
|
43
45
|
|
|
44
46
|
- **Function-valued options are compared by identity (6.10)**: `update()` skips a redundant render by comparing the incoming options with the previous ones. Passing a *different* function (a new `dataLabels.formatter`, custom tooltip, `plotOptions.unit.positions`) gets the render it asked for; passing the *same* function twice still skips. Building a fresh closure on every update means a render every time.
|
|
45
47
|
- **A type change re-chooses type defaults (6.9)**: `updateOptions({ chart: { type } })` now re-picks the defaults that decide what a chart reads, says, hit-tests, or offers as interaction (e.g. a boxPlot-to-violin switch gets the right tooltip formatter). Deliberate paint choices and anything you set yourself are never re-chosen.
|
|
48
|
+
- **Your options are copied, never written into (8.1)**: the constructor, `updateOptions` and `updateSeries` leave the objects you pass exactly as you wrote them, so one options object can safely seed two charts. The merged, live config is `chart.w.config` (not in the shipped types).
|
|
49
|
+
- **A destroyed chart is inert, not broken (8.1)**: `updateOptions`, `updateSeries` and `appendSeries` on it log a warning and resolve with the chart instead of throwing (`appendData` resolves without a warning), and `render()` draws it afresh.
|
|
46
50
|
|
|
47
51
|
---
|
|
48
52
|
|
|
@@ -64,9 +68,9 @@ Introduced in **6.5.0**, tightened in **6.7.0**. Not every feature is free. Nine
|
|
|
64
68
|
- the `unit` / `waffle` chart type (premium since **6.6.0**, the first premium chart type)
|
|
65
69
|
- the `raincloud` chart type (premium since **7.1.0**)
|
|
66
70
|
|
|
67
|
-
**Everything else is free and never gated**: every other chart type (the Tier 2 `sunburst`, `violin`, `icicle`, `waterfall`, `dumbbell` and `streamgraph` included), and every other module (Weave, Strata / canvas, Marks, Facet / themes, Cadence, drilldown, streaming, exports, legend, toolbar, annotations, keyboard, stats). Free here means never watermarked, not licence-free: the Community licence covers only organisations under $2M in annual revenue, operating budget, funding or equivalent resources, whichever is highest, across parent, affiliates and entities under common control (see LICENSE.md).
|
|
71
|
+
**Everything else is free and never gated**: every other chart type (the Tier 2 `sunburst`, `violin`, `icicle`, `waterfall`, `dumbbell` and `streamgraph` included), and every other module (Weave, Strata / canvas, Marks, Facet / themes, Cadence, drilldown, radial targets, streaming, exports, legend, toolbar, annotations, keyboard, stats). Free here means never watermarked, not licence-free: the Community licence covers only organisations under $2M in annual revenue, operating budget, funding or equivalent resources, whichever is highest, across parent, affiliates and entities under common control (see LICENSE.md).
|
|
68
72
|
|
|
69
|
-
**Premium and Tier 2 are separate questions.** Premium is about the watermark; Tier 2 is about the bundle. Since 8.0 every premium item is Tier 2, but Tier 2 is not all premium: `renderer-canvas`, `drilldown`, `waterfall`, `dumbbell`, `streamgraph`, `sunburst`, `violin` and `icicle` are Tier 2 and free. The full bundle carries all of them, and the premium ones still watermark there.
|
|
73
|
+
**Premium and Tier 2 are separate questions.** Premium is about the watermark; Tier 2 is about the bundle. Since 8.0 every premium item is Tier 2, but Tier 2 is not all premium: `renderer-canvas`, `drilldown`, `radial-targets`, `waterfall`, `dumbbell`, `streamgraph`, `sunburst`, `violin` and `icicle` are Tier 2 and free. The full bundle carries all of them, and the premium ones still watermark there.
|
|
70
74
|
|
|
71
75
|
### Setting a license
|
|
72
76
|
|
|
@@ -149,7 +153,7 @@ trellis: { by: 'facet', minPanelWidth: 260 },
|
|
|
149
153
|
|
|
150
154
|
**API.** `chart.getPanels()` returns the panels in grid order; `chart.getPanel(key)` returns one panel's own ApexCharts instance (the escape hatch to every per-chart API the trellis does not re-expose); `chart.promotePanel(key)` / `chart.restorePanels()` drive the promotion from code. `ApexCharts.trellis(el, options)` is the imperative constructor: it creates the host and starts rendering it (a later `render()` settles with the same mount). It returns `null`, with a console warning, when the trellis feature is not loaded, so check the return before calling panel methods.
|
|
151
155
|
|
|
152
|
-
**Events.** `panelMounted`, `trellisMounted`, `panelPromoted` and `panelRestored` fire through `chart.events` (7.7.0) as well as `addEventListener`, with `(chart, payload)`; they are not in the shipped types. On scatter and bubble panels `dataPointIndex` indexes the panel's own data. To turn a trellis back into one chart, pass `trellis: null` to `updateOptions` (a cast in TypeScript); leaving the key out keeps the grid.
|
|
156
|
+
**Events.** `panelMounted`, `trellisMounted`, `panelPromoted` and `panelRestored` fire through `chart.events` (7.7.0) as well as `addEventListener`, with `(chart, payload)`; they are not in the shipped types. On scatter and bubble panels `dataPointIndex` indexes the panel's own data. To turn a trellis back into one chart, pass `trellis: null` to `updateOptions` (typed, and reliable, since 8.5; earlier it needed a cast in TypeScript); leaving the key out keeps the grid.
|
|
153
157
|
|
|
154
158
|
**Annotations** take `scope`: absent or `'trellis'` draws in every panel through each panel's own scale, a key or array of keys restricts it.
|
|
155
159
|
|
|
@@ -188,8 +192,9 @@ The `setup(api)` facade:
|
|
|
188
192
|
|
|
189
193
|
- `api.on(hook, fn)` / `api.off(hook, fn)`: hooks: `'afterParse' | 'afterScales' | 'draw' | 'afterUpdate' | 'destroy'`.
|
|
190
194
|
- `api.layer(opts?)`: a plugin-owned drawing surface (`path`, `line`, `rect`, `circle`, `text`, `clear`); call it inside draw handlers only, layers are wiped each pass.
|
|
191
|
-
- `api.scales` (readonly): `x(v)`, `y(v, axis?)`, `domainX`, `domainY(axis?)`, `gridWidth`, `gridHeight`, `ratios`. **`null` on a non-axis chart**, so it is a fact about the chart rather than about the host and is deliberately not a capability.
|
|
192
|
-
- `api.
|
|
195
|
+
- `api.scales` (readonly): `x(v)`, `y(v, axis?)`, `domainX`, `domainY(axis?)`, `gridWidth`, `gridHeight`, `ratios`, and *(8.0.1, capability `scale-orientation`)* `transposed` plus `point(x, y, axis?)`. **`null` on a non-axis chart**, so it is a fact about the chart rather than about the host and is deliberately not a capability. On a horizontal bar `transposed` is `true`: `x(v)` runs down the grid height and `y(v)` across the width, so place a datum with `point(x, y)` rather than pairing `x()` and `y()` yourself.
|
|
196
|
+
- `api.radialScales` (readonly, *8.5*, capability `radial-scales`): the dial a radialBar or gauge drew (centre, ring and band radii, angles, `angle(v)`, `point(v, r?)`), the same object as `chart.getRadialScales()`; `null` on every other type, where `scales` applies. Also on every hook payload as `radialScales`.
|
|
197
|
+
- `api.data` (readonly): `[{ name?, hidden, color?, points: [{ x, y }], raw, observations }]`. *(8.0.1, capability `observations`)* `observations` is the raw sample behind a histogram's bins or a boxPlot / violin summary derived from `points` (`{ values, byPoint }`, `byPoint[j]` `null` where that datum was precomputed), or `null` when `points` are the caller's own values.
|
|
193
198
|
- `api.theme`: `{ mode, foreColor, seriesColor(i), token(name) }`.
|
|
194
199
|
- `api.store`: per-instance mutable state bag.
|
|
195
200
|
- `api.emit(name, detail?)`: dispatches `plugin:<name>:<event>` on the chart; `api.chart`, `api.el`, `api.name`, `api.version`, `api.options` round out the facade.
|
|
@@ -292,13 +297,26 @@ api.on('draw', () => {
|
|
|
292
297
|
- **Declare from the draw handler.** Declarations are cleared with the layers at the start of every draw, so an inventory cannot outlive the drawing it describes. Declaring the same id twice replaces it rather than growing a duplicate row.
|
|
293
298
|
- **Annotations carry no caller id.** The `id` on a point annotation is the key of a deferred-execution entry rather than a handle on the drawing, so entries fall back to `annotation:<type>:<index>` and take their label from `label.text` where the caller wrote one.
|
|
294
299
|
|
|
300
|
+
### v7: draw a part of each value (`highlight`, 8.1)
|
|
301
|
+
|
|
302
|
+
A plugin with a second number per datum used to have only `markDerived()`, which adds a series, and a series costs the caller a legend entry, a tooltip row, an export column and a rescaled axis. `api.highlight()` draws the part solid inside the slot the value already occupies, with the whole faded behind it, as the highlight filter does:
|
|
303
|
+
|
|
304
|
+
```js
|
|
305
|
+
const h = api.highlight([{ series: 'Revenue', values: [12, null, 30] }]) // parallel to that series' data
|
|
306
|
+
if (h) { h.update([{ series: 'Revenue', values: [8, 4, 20] }]); h.release() }
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**It returns `null`** when the highlight-filter feature is not loaded on the page, the chart is not an axis chart, the type draws no parts (a nested treemap included), or the caller is already showing parts of their own. Check the return on every call, since three of those can change on the caller's next update. Registering, updating and releasing each re-render the chart, coalesced to one render per turn.
|
|
310
|
+
|
|
311
|
+
**Dash values are patterns now (8.5).** `api.info.stroke.dashArray` may be a pattern string (`'8 3 2 3'`) or a per-series array whose entries are themselves patterns, and `layer.path` / `layer.line` take `dash` in the same forms, so a plugin that assumed a number must handle both.
|
|
312
|
+
|
|
295
313
|
### The types a plugin author works with
|
|
296
314
|
|
|
297
|
-
Declared in the shipped `apexcharts.d.ts`: `ApexPluginAPI` (the `setup(api)` facade), `ApexPluginSeries`, `ApexPluginScales`, `ApexPluginLayer`, `ApexPluginHook`, `ApexPluginPayload`,
|
|
315
|
+
Declared in the shipped `apexcharts.d.ts`: `ApexPluginAPI` (the `setup(api)` facade), `ApexPluginSeries`, `ApexPluginScales`, `ApexPluginLayer`, `ApexPluginHook`, `ApexPluginPayload`, for the v6 additions `ApexPluginChartInfo` (`api.info`), `ApexPluginPointerEvent` (the `pointer` payload), `ApexPluginClaim` (`{ release(), update(entries) }`) and `ApexDrawnItem` (a `drawn()` row), and, added in 8.x, `ApexPluginHighlight` and `ApexPluginHighlightEntry` (`highlight()`), `ApexRadialScales` (`radialScales`) and `ApexDashPattern` (dash values).
|
|
298
316
|
|
|
299
|
-
### Typing gap (still present at 8.
|
|
317
|
+
### Typing gap (still present at 8.7.0)
|
|
300
318
|
|
|
301
|
-
`api.categories` and `data[].raw` are real at runtime (both shipped in v2) but are **not declared** in the shipped `apexcharts.d.ts`: `ApexPluginAPI` has no `categories` member and `ApexPluginSeries` is typed as `{ name?, hidden, color?, points }`. TypeScript rejects both. Cast the facade where you need them, and do not read the absence as "removed".
|
|
319
|
+
`api.categories` and `data[].raw` are real at runtime (both shipped in v2) but are **not declared** in the shipped `apexcharts.d.ts`: `ApexPluginAPI` has no `categories` member and `ApexPluginSeries` is typed as `{ name?, hidden, color?, points, observations }`, without `raw`. TypeScript rejects both. Cast the facade where you need them, and do not read the absence as "removed".
|
|
302
320
|
|
|
303
321
|
---
|
|
304
322
|
|
|
@@ -446,6 +464,8 @@ const options = {
|
|
|
446
464
|
|
|
447
465
|
`await chart.refreshTokens()` re-reads the cascade after a runtime token change that does not itself trigger a render.
|
|
448
466
|
|
|
467
|
+
**Built-in palettes and the mode (8.7).** `theme.palette` (`'palette1'` to `'palette10'`) that you name, in the options, `window.Apex` or an `updateOptions` payload, is kept in either mode. Left unset, the palette follows the mode: `'palette4'` in dark mode, `'palette1'` otherwise. Before 8.7 a named `'palette1'` in dark mode (or `'palette4'` in light) was swapped for the mode's default.
|
|
468
|
+
|
|
449
469
|
---
|
|
450
470
|
|
|
451
471
|
## Cadence: pluggable easing
|
|
@@ -558,6 +578,16 @@ Per type:
|
|
|
558
578
|
|
|
559
579
|
---
|
|
560
580
|
|
|
581
|
+
## Radial targets (8.5)
|
|
582
|
+
|
|
583
|
+
`import 'apexcharts/features/radial-targets'`: **Tier 2** (not in the default bundle; script tag `dist/features/radial-targets.js` after the ApexCharts script, or the full bundle). Free, never watermarked. It shipped as an add-on in 8.5 and was never in the default bundle.
|
|
584
|
+
|
|
585
|
+
Draws `plotOptions.radialBar.targets`: marks at a value on a ring (a target, a limit, last period's reading) on a radialBar, every ring of it, or a gauge of either shape. They sweep in with their ring, move from the old value on an update, hide with a legend-hidden ring and never take the pointer. Options and an example are in "Targets" in `references/circular-charts.md`.
|
|
586
|
+
|
|
587
|
+
**Without the import** the dial draws exactly as before, without the targets, and the console warns once per chart (not once per update), naming the import, the script-tag file and `apexcharts.full.min.js`. Nothing throws. Targets on any type other than radialBar or gauge are never read. The dial geometry the targets sit on, `chart.getRadialScales()`, is core and works without the add-on.
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
561
591
|
## Ink: direct-manipulation annotation authoring
|
|
562
592
|
|
|
563
593
|
`import 'apexcharts/features/ink'`: **Tier 2** (not in the default bundle) and **premium**.
|
|
@@ -747,7 +777,9 @@ chart.drillUp()
|
|
|
747
777
|
chart.drillToRoot()
|
|
748
778
|
```
|
|
749
779
|
|
|
750
|
-
**Async failure semantics (v6.9):** a failed fetch never strands the view. On a throw, a rejection, or a resolver returning
|
|
780
|
+
**Async failure semantics (v6.9):** a failed fetch never strands the view. On a throw, a rejection, or a resolver returning neither a `data` nor a `series` array, the chart stays where it was, the breadcrumb is untouched, nothing is cached, and `drillDownError` fires. A second click while one resolve is in flight is ignored rather than starting a second request.
|
|
781
|
+
|
|
782
|
+
*(8.4)* `onDrillDown` may resolve with `series` (several series, for a grouped or stacked level) instead of `data`, and may omit `id` (it defaults to the requested one). A level that settles after the viewer has navigated elsewhere is cached but not drilled into, and the overrides a level carries (`colors`, `plotOptions`, `xaxis` and the rest) are undone on the way back up.
|
|
751
783
|
|
|
752
784
|
*(8.0)* A child level naming a Tier 2 chart type whose renderer the page has not loaded (`unit` / `waffle`, `sunburst`, `icicle`, `violin`, and `raincloud`, which draws through violin) is refused too: the update stops before anything moves, the level comes back off the stack, `drillDownError` fires with the error, and the `chart.drillDown(id)` promise rejects. A `waterfall`, `dumbbell` or `streamgraph` level without its feature is not refused: it navigates, then draws blank with one console warning. Load each level's chart type and feature as well as the drilldown feature.
|
|
753
785
|
|
|
@@ -797,7 +829,7 @@ const options = {
|
|
|
797
829
|
|
|
798
830
|
## Common Pitfalls
|
|
799
831
|
|
|
800
|
-
1. **Assuming the default bundle carries everything *(the #1 upgrade mistake, v6 to v7 and again 7 to 8)*.** In v6, `import ApexCharts from 'apexcharts'` was enough for every feature. At 8.0 each of these needs its own import on top of it: the features `trellis`, `storyboard`, `perspectives`, `ink`, `renderer-canvas`, `link`, `measure`, `history`, `context-menu`, `highlight-filter`, `drilldown`, `waterfall`, `dumbbell` and `
|
|
832
|
+
1. **Assuming the default bundle carries everything *(the #1 upgrade mistake, v6 to v7 and again 7 to 8)*.** In v6, `import ApexCharts from 'apexcharts'` was enough for every feature. At 8.0 each of these needs its own import on top of it: the features `trellis`, `storyboard`, `perspectives`, `ink`, `renderer-canvas`, `link`, `measure`, `history`, `context-menu`, `highlight-filter`, `drilldown`, `waterfall`, `dumbbell`, `streamgraph` and `radial-targets` (8.5), and the `unit` / `waffle`, `sunburst`, `violin`, `icicle` and `raincloud` chart types. Read the console: each names the import, the script-tag file and `apexcharts.full.min.js`.
|
|
801
833
|
2. **Forgetting the feature import on a tree-shaken build**: a Tier 1 feature is in the default bundle but not in `apexcharts/core` or a per-type entry, so those builds still need `import 'apexcharts/features/<name>'`.
|
|
802
834
|
3. **Reaching for `apexcharts/features/all` to fix either of the above**: it is the Tier 1 set only, by design (`tests/unit/feature-tier-budget.spec.js` upstream fails the build if a Tier 2 feature reappears in it). The entry that does have everything is `apexcharts/full`.
|
|
803
835
|
4. **Using `api.zeroY` in a custom mark**: it does not exist. Use `ctx.scales.y(0)` for the baseline.
|
|
@@ -22,7 +22,7 @@ The wrappers' standard components load the default ApexCharts bundle, which sinc
|
|
|
22
22
|
|---|---|
|
|
23
23
|
| `unit`/`waffle`, `sunburst`, `violin`, `icicle` | `import 'apexcharts/unit'` (or `/sunburst`, `/violin`, `/icicle`) |
|
|
24
24
|
| `raincloud` | `import 'apexcharts/raincloud'` |
|
|
25
|
-
| `waterfall`, `dumbbell`, `streamgraph`, drilldown or another Tier 2 feature | `import 'apexcharts/features/<name>'` (`highlightFilter` is `features/highlight-filter`) |
|
|
25
|
+
| `waterfall`, `dumbbell`, `streamgraph`, drilldown or another Tier 2 feature | `import 'apexcharts/features/<name>'` (`highlightFilter` is `features/highlight-filter`, `plotOptions.radialBar.targets` is `features/radial-targets`) |
|
|
26
26
|
| Everything | `import 'apexcharts/full'`, which reuses the default bundle the wrapper already loads |
|
|
27
27
|
|
|
28
28
|
```jsx
|
|
@@ -242,7 +242,7 @@ updateChart() {
|
|
|
242
242
|
<div id="chart"></div>
|
|
243
243
|
|
|
244
244
|
<!-- CDN, pinned to a release -->
|
|
245
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
245
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/apexcharts.min.js"></script>
|
|
246
246
|
|
|
247
247
|
<script>
|
|
248
248
|
const options = {
|
|
@@ -260,16 +260,16 @@ updateChart() {
|
|
|
260
260
|
|
|
261
261
|
```html
|
|
262
262
|
<!-- default bundle -->
|
|
263
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
263
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/apexcharts.min.js"></script>
|
|
264
264
|
<!-- one add-on next to it: an opt-in chart type -->
|
|
265
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
265
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/sunburst.js"></script>
|
|
266
266
|
|
|
267
267
|
<!-- or the full bundle: every chart type and feature, no add-ons -->
|
|
268
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.
|
|
268
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/8.6.0/apexcharts.full.min.js"></script>
|
|
269
269
|
|
|
270
270
|
<!-- the same files on jsDelivr keep the dist/ folder in the path -->
|
|
271
|
-
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8.
|
|
272
|
-
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8.
|
|
271
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8.6.0/dist/apexcharts.min.js"></script>
|
|
272
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8.6.0/dist/sunburst.js"></script>
|
|
273
273
|
```
|
|
274
274
|
|
|
275
275
|
**Always write an exact version**, as above, never a major channel (`apexcharts@<major>`) or the unversioned URL: sandboxes that host generated pages (artifacts, previews) commonly reject a URL without an exact version, and an exact pin keeps a page working when the next major changes what the default bundle holds. **Never write a 3.x or 4.x URL** (`.../apexcharts/3.54.1/...`): those are releases from 2024 and early 2025, and this skill does not describe them. If an environment only accepts an older release, use the newest one it accepts with the same major version as the URLs above, since this skill applies to that whole major. To stay on an older major, pin a release from it. The other add-ons are `unit.js`, `violin.js`, `icicle.js` and `features/<name>.js` beside `apexcharts.min.js`, and may load before or after the main script.
|
|
@@ -283,3 +283,4 @@ updateChart() {
|
|
|
283
283
|
3. **Not destroying on unmount (vanilla API in React/Vue)** — causes memory leaks and duplicate charts. The official wrappers handle this automatically.
|
|
284
284
|
4. **Mutating config objects in place (Vue)** — deep mutations may not trigger reactivity. Replace the entire object or use `ref` at the right level.
|
|
285
285
|
5. **Rendering in hidden containers** — charts rendered in hidden tabs/modals have zero dimensions. Call `chart.updateOptions({})` or trigger a resize after showing the container.
|
|
286
|
+
6. **Sizing the host element *(v8.6)***: ApexCharts no longer writes a `min-height` on the element you render into; the height it reserves is a `min-height` on its own `.apexcharts-canvas` wrapper. A `min-height` you give the host (style prop or class) now applies while the chart is mounted and survives `destroy()`, so a destroy and re-create on the same element (React StrictMode's double mount, Vue and Angular refreshes) no longer leaves the next chart in a host with no minimum height. Code that read the reservation from the host should read it from `.apexcharts-canvas`.
|
|
@@ -179,7 +179,9 @@ plotOptions: {
|
|
|
179
179
|
parents: { // how branch containers are drawn once the data is nested
|
|
180
180
|
show: 'auto' // 'auto' (on when the data carries children) | true | false
|
|
181
181
|
// plus header/label styling and a tooltip.formatter receiving
|
|
182
|
-
// { name, value, depth, leafCount, percentOfParent, percentOfTotal, node, w
|
|
182
|
+
// { name, value, depth, leafCount, percentOfParent, percentOfTotal, node, w,
|
|
183
|
+
// series, seriesIndex, dataPointIndex: -1, ctx } (the last four since v8.4)
|
|
184
|
+
// and returning markup, an Element, or null / undefined / false to keep the built-in rows
|
|
183
185
|
},
|
|
184
186
|
levels: [ /* per-depth overrides of `parents`, indexed from the outermost drawn group */ ]
|
|
185
187
|
}
|
|
@@ -188,6 +190,8 @@ plotOptions: {
|
|
|
188
190
|
|
|
189
191
|
The hierarchy resolver is shared with sunburst, including the `drilldown: '<id>'` adapter (opted into via `nested.drilldownAsLevels`).
|
|
190
192
|
|
|
193
|
+
**Branch tooltips (v8.2, v8.4).** A hovered branch gets its own tooltip (`.apexcharts-treemap-tooltip`, v8.2) with the branch name, total and shares. Since v8.4 `tooltip.custom` runs on branches too, called as the sunburst and icicle call it: `dataPointIndex: -1`, `seriesIndex` the branch's series, `node`, `value` (the branch total), `percentOfParent` and `percentOfTotal` (0 to 100, one decimal). `plotOptions.treemap.parents.tooltip.formatter`, when set, owns branch tooltips instead and `tooltip.custom` keeps the leaves. A `null` / `undefined` return keeps the built-in rows. **A `tooltip.custom` written for leaves must return `null` when `node` is set**, or it reads `series[seriesIndex][-1]` on every branch hover.
|
|
194
|
+
|
|
191
195
|
### Icicle (v7.6)
|
|
192
196
|
|
|
193
197
|
Same hierarchy as the sunburst, drawn in cartesian coordinates: one band per depth level, each child sized inside its parent's extent along the value axis. Axis-style `[{ data: [...] }]` wrapper, `{ x, y, children }` nodes to any depth.
|
|
@@ -213,6 +217,7 @@ const options = {
|
|
|
213
217
|
- A branch may **omit its own `y`** and be the sum of its children. This is the documented shape for both partition types, and it only started working in v7.6: before that the non-axis parser dropped any node carrying `children` without `x` and `y`, and the chart drew nothing at all while warning about pie data.
|
|
214
218
|
- A node may carry `drilldown: '<id>'` instead of `children`, and the matching `drilldown.series` entry is read as the next level. It is read as plain data, so no drilldown feature import is needed.
|
|
215
219
|
- Sibling order follows the array by default (`sort: 'none'`). Set `plotOptions.icicle.sort` to `'value'` or `'name'` to override it.
|
|
220
|
+
- `tooltip.custom` *(v8.4)* runs once per hovered node with `{ seriesIndex: 0, dataPointIndex: -1, node, percentOfParent, percentOfTotal, series, w, ctx }`, the same call the sunburst makes; return markup or an Element, or `null` to keep the built-in row. Node names are escaped in the built-in tooltip *(v8.3.1)*, so markup in a name shows as text.
|
|
216
221
|
|
|
217
222
|
**Choosing between icicle and sunburst.** Both resolve the same tree. An icicle keeps labels horizontal at every depth and puts depth on a straight axis, so same-depth siblings line up across branches and deep trees stay readable; a sunburst spends its area radially and reads better for shallow, wide trees. `direction: 'up'` is the flame-graph orientation, for call stacks and path funnels.
|
|
218
223
|
|
|
@@ -382,3 +387,4 @@ A click that would not change the view is refused rather than performed: clickin
|
|
|
382
387
|
6. **`chart.type: 'icicle'` on the default bundle (v7.6)**: icicle is Tier 2 and the default build carries no class for it, so the chart fails to render and the console names the import. Add `import 'apexcharts/icicle'` next to `import ApexCharts from 'apexcharts'` (or load `dist/icicle.js`). The default `apexcharts.js` does not carry the class; the full bundle (`apexcharts/full`, `dist/apexcharts.full.min.js`, v8.0) does.
|
|
383
388
|
7. **Reaching for `zoomType: 'both'` to make a branch fill the plot** — `'value'` already stretches the branch across the full width; what `'both'` additionally does is move every level, which costs the reader their place in the tree. Change it only when the ancestors genuinely do not matter.
|
|
384
389
|
8. **Expecting `sort: 'value'` on a flame graph** — `'name'` is the flame-graph convention, because it holds a frame in the same place across profiles so two runs of one program can be compared by eye.
|
|
390
|
+
9. **A data-point `tooltip.custom` on a nested treemap, sunburst or icicle** *(v8.4)*: it now runs on branches and partition nodes too, with `dataPointIndex: -1` and the hovered `node`. Return `null` when `opts.node` is set to keep the built-in tooltip there, or give treemap branches `plotOptions.treemap.parents.tooltip.formatter`.
|
package/references/ssr.md
CHANGED
|
@@ -50,6 +50,8 @@ const svgString = await ApexCharts.renderToString(
|
|
|
50
50
|
// svgString is raw <svg>...</svg> markup
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
The legend is HTML beside the SVG, so this standalone SVG carries **no legend** and its plot fills the chart. Use `renderToHTML` for a chart with its legend.
|
|
54
|
+
|
|
53
55
|
### renderToHTML(options, ssrOptions?)
|
|
54
56
|
|
|
55
57
|
Returns an HTML string with a wrapper `<div>` containing the SVG, ready for hydration:
|
|
@@ -76,6 +78,8 @@ const htmlString = await ApexCharts.renderToHTML(
|
|
|
76
78
|
// travels in data-apexcharts-config, which is what hydration reads.
|
|
77
79
|
```
|
|
78
80
|
|
|
81
|
+
*(v8.2)* The HTML includes the legend and its stylesheet beside the SVG, as the browser draws it; before 8.2 it had none. Set `legend: { show: false }` for the old output. Series names and categories in it are escaped *(v8.0.1, v8.4)*, so data you do not control cannot inject markup.
|
|
82
|
+
|
|
79
83
|
---
|
|
80
84
|
|
|
81
85
|
## Client-Side Hydration
|
|
@@ -92,6 +96,8 @@ import ApexCharts from 'apexcharts/ssr' // not 'apexcharts' or 'apexcharts/cli
|
|
|
92
96
|
const chart = ApexCharts.hydrate(document.querySelector('[data-apexcharts-hydrate]'))
|
|
93
97
|
```
|
|
94
98
|
|
|
99
|
+
The options you passed to `renderToHTML` travel with it and **stand as written** on the client *(v8.1)*: a `chart.animations.enabled: false` or `chart.toolbar.show: false` you set for the server stays off after hydration (before 8.1 hydration switched both back on). To change them on the client, pass them in `clientOptions`, e.g. `hydrate(el, { chart: { toolbar: { show: true } } })`.
|
|
100
|
+
|
|
95
101
|
### hydrateAll(selector?, clientOptions?)
|
|
96
102
|
|
|
97
103
|
```js
|
|
@@ -26,7 +26,7 @@ import ApexCharts from 'apexcharts/full' // script tag: dist/apexcharts.full.m
|
|
|
26
26
|
| 8.0.0 default bundle | 263,188 B (**-9.8%**) |
|
|
27
27
|
| 8.0.0 full bundle | 381,135 B |
|
|
28
28
|
|
|
29
|
-
Unversioned CDN URLs serve 8.
|
|
29
|
+
Unversioned CDN URLs serve the latest 8.x release. Pin a 7.x release to stay on 7.
|
|
30
30
|
|
|
31
31
|
## ⚠️ What changed in v7.0
|
|
32
32
|
|
|
@@ -166,12 +166,13 @@ Required whatever entry point you used, the default `apexcharts` bundle included
|
|
|
166
166
|
| Waterfall *(v7.1; Tier 2 since v8.0)* | `import 'apexcharts/features/waterfall'` | 2.8 KB | no | The `waterfall` chart type |
|
|
167
167
|
| Dumbbell *(v7.1; Tier 2 since v8.0)* | `import 'apexcharts/features/dumbbell'` | 2.1 KB | no | The `dumbbell` chart type |
|
|
168
168
|
| Raincloud *(v7.1)* | `import 'apexcharts/raincloud'` | 2.4 KB + violin 6.4 KB | yes | The `raincloud` chart type. The entry brings violin and the feature; `apexcharts/features/raincloud` alone works only where violin is already registered *(v8.0)* |
|
|
169
|
+
| Radial targets *(v8.5)* | `import 'apexcharts/features/radial-targets'` | 2.9 KB (at 8.7.0) | no | `plotOptions.radialBar.targets`: target and limit marks on a radialBar ring or a gauge. Never in the default bundle: it shipped as an add-on |
|
|
169
170
|
|
|
170
171
|
Storyboard registers Perspectives, so importing both costs no more than Storyboard alone.
|
|
171
172
|
|
|
172
173
|
**`apexcharts/features/all` does not include Tier 2**, by design: upstream has a tier-budget test that fails the build if a Tier 2 feature reappears in it.
|
|
173
174
|
|
|
174
|
-
**Nothing fails silently on Tier 2.** Each module warns in the console when its configuration is present but the module is not, and the warning names the ESM import, the script-tag file and `apexcharts.full.min.js`. Where the chart can still draw something sensible it does and says what it did instead: a trellis renders as a single chart, `renderer: 'canvas'` falls back to SVG.
|
|
175
|
+
**Nothing fails silently on Tier 2.** Each module warns in the console when its configuration is present but the module is not, and the warning names the ESM import, the script-tag file and `apexcharts.full.min.js`. Where the chart can still draw something sensible it does and says what it did instead: a trellis renders as a single chart, `renderer: 'canvas'` falls back to SVG, a radialBar or gauge draws its dial without `plotOptions.radialBar.targets`.
|
|
175
176
|
|
|
176
177
|
---
|
|
177
178
|
|
|
@@ -210,7 +211,7 @@ It depends on the tier.
|
|
|
210
211
|
- `addXaxisAnnotation()` does nothing
|
|
211
212
|
- `dataURI()` / `exportToCSV()` throw because the feature isn't registered
|
|
212
213
|
|
|
213
|
-
**Tier 2 features announce themselves.** Each warns in the console when its configuration is present but the module is not, naming the ESM import, the script-tag file and `apexcharts.full.min.js`, and degrades predictably where it can: a `trellis` config renders as one ordinary chart, `renderer: 'canvas'` falls back to SVG. If a chart is quietly missing a feature you configured, **check the console before the config**. Since 7.9.1 the minified `apexcharts.min.js` prints these warnings too.
|
|
214
|
+
**Tier 2 features announce themselves.** Each warns in the console when its configuration is present but the module is not, naming the ESM import, the script-tag file and `apexcharts.full.min.js`, and degrades predictably where it can: a `trellis` config renders as one ordinary chart, `renderer: 'canvas'` falls back to SVG, targets on a radialBar or gauge are left off the dial (one warning per chart, not one per update). If a chart is quietly missing a feature you configured, **check the console before the config**. Since 7.9.1 the minified `apexcharts.min.js` prints these warnings too.
|
|
214
215
|
|
|
215
216
|
**Opt-in chart types throw *(v8.0)*.** `unit`, `waffle`, `sunburst`, `violin`, `icicle` and `raincloud` without their entry make `render()` reject, and the console prints one error naming the import, the script tag and the full bundle. An `updateOptions()` that switches to an unloaded type keeps the current chart.
|
|
216
217
|
|
|
@@ -291,7 +292,7 @@ export default {
|
|
|
291
292
|
|
|
292
293
|
## Common Pitfalls
|
|
293
294
|
|
|
294
|
-
1. **Assuming the default bundle still has everything *(v7, v8)***: the Tier 2 chart types (`unit`/`waffle`, `sunburst`, `violin`, `icicle`, `raincloud`) and Tier 2 features (the nine since 7.0, highlight-filter since 7.9,
|
|
295
|
+
1. **Assuming the default bundle still has everything *(v7, v8)***: the Tier 2 chart types (`unit`/`waffle`, `sunburst`, `violin`, `icicle`, `raincloud`) and Tier 2 features (the nine since 7.0, highlight-filter since 7.9, drilldown, waterfall, dumbbell and streamgraph since 8.0, and radial-targets since 8.5) need their own import on top of `import ApexCharts from 'apexcharts'`, or the full bundle. This is the most common upgrade failure, v6 to v7 and v7 to v8.
|
|
295
296
|
2. **Reaching for `apexcharts/features/all` to fix it**: that is the Tier 1 set by design and pulls in no Tier 2 module.
|
|
296
297
|
3. **Missing feature imports on a tree-shaken build**: Tier 1 features fail silently. If legend/toolbar/annotations don't appear, check imports.
|
|
297
298
|
4. **Adding a per-type entry for a type the default bundle already has** (`apexcharts/line`, `apexcharts/bar`, `apexcharts/waterfall` next to `apexcharts`): that is a second copy of the renderer. Next to `apexcharts`, add only the opt-in entries (`apexcharts/unit`, `/sunburst`, `/violin`, `/icicle`, `/raincloud`) and `apexcharts/features/*`. *(v7.0 fixed the related internal bug where the default bundle inlined its own core copy while add-ons resolved `apexcharts/core`, so an app importing both got two classes, ~130 KB gzipped of duplicate core, and a feature that never registered. They now share one core.)*
|