apexcharts-skill 3.0.0 → 4.0.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 +71 -44
- package/README.md +8 -8
- package/SKILL.md +126 -82
- package/package.json +1 -1
- package/references/bar-charts.md +26 -8
- package/references/cartesian-charts.md +27 -1
- package/references/circular-charts.md +24 -7
- package/references/feature-platform.md +195 -29
- package/references/financial-charts.md +28 -12
- package/references/framework-wrappers.md +36 -6
- package/references/grid-charts.md +97 -4
- package/references/ssr.md +40 -19
- package/references/tree-shaking.md +78 -43
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
# Feature Platform: ApexCharts
|
|
2
2
|
|
|
3
|
-
ApexCharts ships an opt-in feature platform on top of the chart core. **Every v5 and v6 config keeps working unchanged in v7**, apart from the two v7.0 breaking changes noted below. Each feature is off by default in config terms and ships as its own `apexcharts/features/*` entry.
|
|
3
|
+
ApexCharts ships an opt-in feature platform on top of the chart core. **Every v5 and v6 config keeps working unchanged in v7**, apart from the two v7.0 breaking changes noted below. In 8.0 the breaking change is what the default bundle carries (next section). Each feature is off by default in config terms and ships as its own `apexcharts/features/*` entry.
|
|
4
4
|
|
|
5
|
-
## ⚠️ Read first:
|
|
5
|
+
## ⚠️ Read first: what is in the default bundle (8.0)
|
|
6
6
|
|
|
7
|
-
Whether you need
|
|
7
|
+
Whether you need an import depends on the feature's or chart type's **tier**. The tiers date from v7.0. **8.0 moved seven items to Tier 2**: the `unit` (with `waffle`), `sunburst` and `violin` chart types, and the `drilldown`, `waterfall`, `dumbbell` and `streamgraph` features. A page that uses one adds its import, or loads the full bundle.
|
|
8
8
|
|
|
9
|
-
- **Tier 1** is in the default `import ApexCharts from 'apexcharts'` bundle: `exports`, `legend`, `toolbar`, `annotations`, `keyboard`, `morph`, `
|
|
10
|
-
- **Tier 2 is not in
|
|
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
|
+
- **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)*, and 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);
|
|
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
|
+
- **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.
|
|
11
14
|
|
|
12
15
|
```js
|
|
13
16
|
import ApexCharts from 'apexcharts'
|
|
14
|
-
import 'apexcharts/features/trellis' // Tier 2:
|
|
17
|
+
import 'apexcharts/features/trellis' // Tier 2: not in the default bundle
|
|
15
18
|
```
|
|
16
19
|
```html
|
|
17
20
|
<script src=".../dist/apexcharts.js"></script>
|
|
18
21
|
<script src=".../dist/features/trellis.js"></script>
|
|
19
22
|
```
|
|
20
23
|
|
|
21
|
-
Nothing fails silently
|
|
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.
|
|
22
25
|
|
|
23
|
-
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. See `references/tree-shaking.md` for the full tier table and per-module sizes.
|
|
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.
|
|
24
27
|
|
|
25
28
|
## Two v7.0 breaking changes
|
|
26
29
|
|
|
27
|
-
1. **`plotOptions.bar.borderRadiusWhenStacked`
|
|
30
|
+
1. **`plotOptions.bar.borderRadiusWhenStacked` was dropped in v7.0, and came back working in v7.4.** In v7.0 it had not been read for some time and was removed as dead config, with corner ownership following the stack's **outer edge** automatically. v7.4 made it a real option again: `'all'` (the default) keeps that look with both stack ends rounded, and `'last'` rounds only the far end and leaves the baseline square. A one-point stack no longer rounds its baseline either. Treat it as live, not as legacy.
|
|
28
31
|
2. **`dataLabels.animate.enabled` now defaults to `true`** (bar and column only). Labels ride to their new position on a data-change update instead of snapping there, so they reflow on the same clock as the bars, markers and axis ticks. Speed and easing follow `chart.animations.dynamicAnimation`. A label that has not moved is a per-label no-op. Set `dataLabels: { animate: { enabled: false } }` for the old behavior.
|
|
29
32
|
|
|
30
33
|
## Behaviors that are on by default
|
|
@@ -32,7 +35,7 @@ Why: 24% of the 6.10.0 default bundle was licence-gated premium code that an unl
|
|
|
32
35
|
Carried over from v6, both respecting `prefers-reduced-motion`:
|
|
33
36
|
|
|
34
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`.
|
|
35
|
-
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 `
|
|
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.
|
|
36
39
|
|
|
37
40
|
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.
|
|
38
41
|
|
|
@@ -45,7 +48,7 @@ Two update behaviors worth knowing (both 6.9/6.10):
|
|
|
45
48
|
|
|
46
49
|
## Licensing: premium features and the trial watermark
|
|
47
50
|
|
|
48
|
-
Introduced in **6.5.0**, tightened in **6.7.0**. Not every feature is free.
|
|
51
|
+
Introduced in **6.5.0**, tightened in **6.7.0**. Not every feature is free. Nine feature modules plus two chart types are **premium** and run under a lightweight, offline license check. They keep working fully without a key (trial mode), but the chart shows an unobtrusive `APEXCHARTS` watermark until an entitled license is set.
|
|
49
52
|
|
|
50
53
|
**The premium set (watermarked until entitled):**
|
|
51
54
|
|
|
@@ -57,12 +60,13 @@ Introduced in **6.5.0**, tightened in **6.7.0**. Not every feature is free. Eigh
|
|
|
57
60
|
- `context-menu` (`contextMenu`)
|
|
58
61
|
- `perspectives` (shareable view state)
|
|
59
62
|
- `history` (undo/redo, Rewind)
|
|
63
|
+
- `highlight-filter` (`highlightFilter`, premium since **7.9.0**; watermarks only while a render draws parts)
|
|
60
64
|
- the `unit` / `waffle` chart type (premium since **6.6.0**, the first premium chart type)
|
|
61
65
|
- the `raincloud` chart type (premium since **7.1.0**)
|
|
62
66
|
|
|
63
|
-
**Everything else is free and never gated**: every other chart type (`sunburst`,
|
|
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).
|
|
64
68
|
|
|
65
|
-
**Premium and Tier 2 are
|
|
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.
|
|
66
70
|
|
|
67
71
|
### Setting a license
|
|
68
72
|
|
|
@@ -78,7 +82,7 @@ Both are typed: `ApexCharts.setLicense(key: string)` (static) and `chart.license
|
|
|
78
82
|
|
|
79
83
|
- **In use, not bundled.** Importing a premium module without actually enabling it does not watermark; only *using* it does.
|
|
80
84
|
- **Live.** A late `setLicense(validKey)` followed by an update clears an on-screen watermark; no full re-render needed. The watermark is re-evaluated on every render/update.
|
|
81
|
-
- **One key across the family.** The key format is shared across
|
|
85
|
+
- **One key across the family.** The key format is shared across every Apex product (apexgantt, apextree, apexsankey, apex-grid-enterprise, apexstock, apexmaps), validated offline with no network call. SSR-safe.
|
|
82
86
|
|
|
83
87
|
### Plan entitlement (6.7.0 behavior change)
|
|
84
88
|
|
|
@@ -127,6 +131,7 @@ trellis: { by: 'facet', minPanelWidth: 260 },
|
|
|
127
131
|
| `columns` | `'auto'` | `'auto'` fits `minPanelWidth` columns into the container. |
|
|
128
132
|
| `minPanelWidth` | `220` | Drives `'auto'` columns and the responsive collapse. |
|
|
129
133
|
| `gap` / `aspectRatio` / `panelHeight` | `12` / `1.6` / none | `panelHeight` wins over `aspectRatio` and `chart.height`. |
|
|
134
|
+
| `minPanelHeight` | `80` | *(7.7.0)* Floor for a height-derived panel, in px. A grid that cannot fit its container overflows and warns by how much instead of shrinking panels past this. Lower it when fitting a short container matters more than legibility. |
|
|
130
135
|
| `order` | `'first-seen'` | Also `'asc'`, `'desc'`, an explicit `string[]`, or a comparator. |
|
|
131
136
|
| `limit` | none | Render only the first N panels (warns about the rest). |
|
|
132
137
|
| `virtualize` | `'auto'` | Mounts only panels intersecting the viewport (plus one row) once the grid exceeds **64 panels**. An unmounted cell keeps its header and a fixed-height skeleton so page height never shifts; a remount restores its zoom window. **`getPanel(key)` returns `null` for an unmounted panel.** |
|
|
@@ -136,13 +141,15 @@ trellis: { by: 'facet', minPanelWidth: 260 },
|
|
|
136
141
|
| `legend` / `toolbar` | `'shared'` | One legend (toggles a series name in every panel) and one zoom/pan/reset toolbar. `'none'` to drop. |
|
|
137
142
|
| `tooltip` | `'panel'` | Card in the hovered panel while the crosshair sweeps all. `'sync'` = a card per panel; `'grid'` = one card near the cursor with a row per panel, composed from the panels' own tooltips so every formatter is honored. |
|
|
138
143
|
| `zoom` | `'sync'` | A zoom in any panel moves every panel. |
|
|
139
|
-
| `promote` | `
|
|
144
|
+
| `promote` | `false` | *(7.7.0 BREAKING: was `true`)* Set `true` to make a header click expand that panel to full width with an "All panels" breadcrumb. `chart.promotePanel(key)` / `chart.restorePanels()` work either way. |
|
|
140
145
|
| `radiusByTotal` | `false` | Pie/donut/polarArea only: scale each panel's radius so its **area** is proportional to the panel's total. Equal-size pies cannot encode magnitude, so set this on a pie trellis. |
|
|
141
146
|
| `targetTicks` | `3` | Tick-interval target for the shared nice y scale, so a small panel wears few labels. |
|
|
142
147
|
| `header` | shown | `{ show, formatter(key, { dimension, index, count }), style }`. |
|
|
143
148
|
| `panel` | none | `(key, { index, seriesNames }) => ApexOptions`, a per-panel override applied last. |
|
|
144
149
|
|
|
145
|
-
**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 and
|
|
150
|
+
**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
|
+
|
|
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.
|
|
146
153
|
|
|
147
154
|
**Annotations** take `scope`: absent or `'trellis'` draws in every panel through each panel's own scale, a key or array of keys restricts it.
|
|
148
155
|
|
|
@@ -181,13 +188,117 @@ The `setup(api)` facade:
|
|
|
181
188
|
|
|
182
189
|
- `api.on(hook, fn)` / `api.off(hook, fn)`: hooks: `'afterParse' | 'afterScales' | 'draw' | 'afterUpdate' | 'destroy'`.
|
|
183
190
|
- `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.
|
|
184
|
-
- `api.scales` (readonly): `x(v)`, `y(v, axis?)`, `domainX`, `domainY(axis?)`, `gridWidth`, `gridHeight`, `ratios`.
|
|
185
|
-
- `api.data` (readonly): `[{ name?, hidden, color?, points: [{ x, y }] }]`.
|
|
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.data` (readonly): `[{ name?, hidden, color?, points: [{ x, y }], raw }]`.
|
|
186
193
|
- `api.theme`: `{ mode, foreColor, seriesColor(i), token(name) }`.
|
|
187
194
|
- `api.store`: per-instance mutable state bag.
|
|
188
195
|
- `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.
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
### Declare the lowest version you can run on, then feature-detect (v2+)
|
|
198
|
+
|
|
199
|
+
`apiVersion` gates the contract so raw internals can keep changing safely, but it is **not** how you ask for a newer member. A plugin declaring a version **newer than the host is skipped outright**, so declaring the latest is how one build stops working on older hosts. Declare the lowest version your plugin can actually run on, and discover anything above that:
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
// v6 hosts: ask by name.
|
|
203
|
+
if (api.can('claim')) { /* ... */ }
|
|
204
|
+
api.capabilities // the whole frozen list, for logging and support
|
|
205
|
+
|
|
206
|
+
// Older hosts, or a plugin that must run on both: probe the member.
|
|
207
|
+
if (typeof api.pointer === 'function') { /* ... */ }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Each capability name is probed off the facade that was actually built, so a member that is ever made conditional drops out of the list instead of being advertised and then missing. Names are permanent once published.
|
|
211
|
+
|
|
212
|
+
The version gate was an exact-match check before v2, which would have disabled every v1 plugin on the first additive change. It is forward-compatible now: an older plugin is served, and only one needing a newer host is skipped.
|
|
213
|
+
|
|
214
|
+
### v2: know what you are attached to
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
api.info // { type, axisChart, datetimeX, horizontalBars,
|
|
218
|
+
// dataLabels: { enabled, enabledOnSeries },
|
|
219
|
+
// stroke: { dashArray }, // v5
|
|
220
|
+
// title } // v6, '' when untitled
|
|
221
|
+
api.categories // display labels per x position, resolved config-first
|
|
222
|
+
api.data[0].raw // the caller's own data array for that series, unparsed
|
|
223
|
+
api.markDerived(['Revenue (forecast)']) // these series are mine, not the caller's
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- **`info` is how a plugin decides whether it applies at all**, instead of adding a series and letting the core warn at the user.
|
|
227
|
+
- **Read `categories`, never `globals.categoryLabels`.** The globals are populated after a mount and empty after an `updateSeries()`, so reading them directly gives real labels on first paint and ordinals after any update.
|
|
228
|
+
- **`raw` is fine to read and wrong to copy**: the three accepted data shapes are not interchangeable, so the normalised `points` are what you compute from.
|
|
229
|
+
- **`markDerived` is not optional if the plugin adds series.** The core cannot tell a plugin's series from the caller's, and the host uses this to keep them out of the initial-series snapshot. Without it, `resetSeries()` hands the user the plugin's computed output as if it were their own data. It is idempotent; pass `[]` when the plugin's series are gone. It is also what puts the plugin's name on those series in `drawn()`.
|
|
230
|
+
|
|
231
|
+
Also fixed in v2: every Weave plugin silently did nothing on a pie, donut or radialBar, because those hold one number per entry and the snapshot called `.map` on it. Each slice is presented as a one-point series now.
|
|
232
|
+
|
|
233
|
+
### v3: reserve room for the plugin's own UI
|
|
234
|
+
|
|
235
|
+
```js
|
|
236
|
+
api.reserve({ right: 120 }) // px; pass null (or all zeros) to give it back
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
A plugin rendering beside the chart cannot make room for itself: the chart sizes from the element the caller handed it, so a sibling inserted there does not narrow it. Reservations are per plugin and summed, so two plugins each asking for a right-hand gutter get one each, and the total is clamped so the chart keeps at least half the container on each axis. An unchanged box does nothing, so calling it on every render is free.
|
|
240
|
+
|
|
241
|
+
### v4: what the viewer is pointing at
|
|
242
|
+
|
|
243
|
+
```js
|
|
244
|
+
const off = api.pointer((e) => {
|
|
245
|
+
// e.type 'enter' | 'leave' | 'select'
|
|
246
|
+
// e.seriesIndex / e.dataPointIndex
|
|
247
|
+
// e.category resolved display label ('Mar'), not an index
|
|
248
|
+
// e.seriesName undefined on a pie
|
|
249
|
+
// e.selected on 'select' only: is the point now in or out
|
|
250
|
+
// e.modifiers { shift, ctrl, alt, meta } (v6)
|
|
251
|
+
})
|
|
252
|
+
off() // pointer() returns its unsubscribe
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Forwards the chart's own `dataPointMouseEnter`, `dataPointMouseLeave` and `dataPointSelection` as one payload, so a plugin does not hit-test the SVG and then disagree with the tooltip on the same pixel. **Nothing here can intercept or cancel**: the tooltip, the selection state and the caller's own `dataPoint*` events are unaffected, and a handler that throws is contained.
|
|
256
|
+
|
|
257
|
+
`category` is the resolved label because a plugin coordinating two charts keys on the label; an index means something different on every chart. `modifiers` is always all four booleans, never partial and never undefined (all false where there was no DOM event), because a plugin reads `e.modifiers.shift` inside a viewer's click and a sometimes-missing key is how that becomes a crash.
|
|
258
|
+
|
|
259
|
+
### v6: set a positional option for your own series (`claim`)
|
|
260
|
+
|
|
261
|
+
`stroke.dashArray` and `dataLabels.enabledOnSeries` are indexed by series position with no per-series form, so a plugin wanting one value for its own series used to write the array covering every series and put the caller's back afterwards.
|
|
262
|
+
|
|
263
|
+
```js
|
|
264
|
+
const claim = api.claim('stroke.dashArray', [
|
|
265
|
+
{ series: 'Revenue (forecast)', value: 6 },
|
|
266
|
+
])
|
|
267
|
+
claim.update([{ series: 'Revenue (forecast)', value: 4 }])
|
|
268
|
+
claim.release()
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
The host resolves a claim **where the option is read**, so nothing is written: there is nothing to restore, releasing is a deletion, and the caller's own `updateOptions` composes with the claim instead of reverting it. Claims resolve in order, so two plugins on one series produce a defined winner rather than whichever ran last.
|
|
272
|
+
|
|
273
|
+
- **Name the series rather than its position where you can.** A name is resolved each time the option is read, so the claim follows that series when the caller adds, removes or reorders others.
|
|
274
|
+
- **Claimable options are an allowlist** (`stroke.dashArray`, `dataLabels.enabledOnSeries` to begin with), each declaring its value type so a wrong one is dropped rather than drawn. An option that is not on the list returns **`null` rather than throwing**, so a plugin built against a newer host degrades instead of breaking. Check the return.
|
|
275
|
+
- Every claim is released on teardown, on destroy, and if the host disables the plugin after repeated errors, so none can outlive the plugin holding it.
|
|
276
|
+
|
|
277
|
+
`api.info.stroke` (v5) exists for the older read-and-restore pattern and reports what is configured, a scalar or one entry per series, copied on the way out. Prefer `claim()` where the host has it: the restore is stale the moment the caller calls `updateOptions`, it leaks if the plugin throws in between, and two plugins doing it at once fight.
|
|
278
|
+
|
|
279
|
+
### v6: an inventory of what is on the chart (`drawn` / `declare`)
|
|
280
|
+
|
|
281
|
+
```js
|
|
282
|
+
api.drawn() // [{ id, kind: 'series' | 'annotation' | 'overlay', label, owner, visible }, ...]
|
|
283
|
+
|
|
284
|
+
api.on('draw', () => {
|
|
285
|
+
api.declare({ id: 'trend-1', label: 'Trend' }) // declare from the draw handler
|
|
286
|
+
})
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`drawn()` reports the series, the caller's annotations and whatever plugins have declared. An ink stroke a viewer drew is an annotation too, but reports `owner: 'ink'` rather than `'core'` (fixed in v7.6.1): crediting a viewer's note to the caller is the one case the `owner` field exists to get right. **Every entry names its `owner`**, and that is the point rather than decoration: the list is only ever as complete as the features that opted in, so a layers panel or an export summary can say what its inventory covers instead of presenting a partial list as everything.
|
|
290
|
+
|
|
291
|
+
- **Read only, deliberately.** Removing or hiding another feature's output would mean one plugin reaching into another's state with no way for the owner to refuse.
|
|
292
|
+
- **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
|
+
- **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
|
+
|
|
295
|
+
### The types a plugin author works with
|
|
296
|
+
|
|
297
|
+
Declared in the shipped `apexcharts.d.ts`: `ApexPluginAPI` (the `setup(api)` facade), `ApexPluginSeries`, `ApexPluginScales`, `ApexPluginLayer`, `ApexPluginHook`, `ApexPluginPayload`, and for the v6 additions `ApexPluginChartInfo` (`api.info`), `ApexPluginPointerEvent` (the `pointer` payload), `ApexPluginClaim` (`{ release(), update(entries) }`) and `ApexDrawnItem` (a `drawn()` row).
|
|
298
|
+
|
|
299
|
+
### Typing gap (still present at 8.0.0)
|
|
300
|
+
|
|
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".
|
|
191
302
|
|
|
192
303
|
---
|
|
193
304
|
|
|
@@ -204,7 +315,7 @@ import 'apexcharts/features/renderer-canvas'
|
|
|
204
315
|
const options = {
|
|
205
316
|
chart: {
|
|
206
317
|
renderer: 'auto', // 'svg' | 'canvas' | 'auto'
|
|
207
|
-
rendererThreshold:
|
|
318
|
+
rendererThreshold: 8000, // point count above which 'auto' picks canvas (default 8000)
|
|
208
319
|
},
|
|
209
320
|
}
|
|
210
321
|
// chart.getActiveRenderer() // => 'svg' | 'canvas'
|
|
@@ -261,7 +372,7 @@ Generic Ctrl-Z over a command journal. Zooms, series toggles, option changes, an
|
|
|
261
372
|
|
|
262
373
|
```js
|
|
263
374
|
const options = {
|
|
264
|
-
chart: { history: { enabled: true, maxDepth:
|
|
375
|
+
chart: { history: { enabled: true, maxDepth: 100, coalesceMs: 250, keyboard: true } }, // those are the defaults
|
|
265
376
|
}
|
|
266
377
|
|
|
267
378
|
chart.history.undo(animate?) // and .redo(animate?)
|
|
@@ -299,6 +410,8 @@ ApexCharts.perspectives.decode(str)
|
|
|
299
410
|
const options = { chart: { perspectives: { serializeOptions: ['colors', 'title'] } } }
|
|
300
411
|
```
|
|
301
412
|
|
|
413
|
+
Calling the static `decode` / `fromURL` counts as using Perspectives for every chart on the page that has the feature loaded, so an unlicensed page shows the watermark on those charts (a script-tag add-on included, since 7.9.1).
|
|
414
|
+
|
|
302
415
|
---
|
|
303
416
|
|
|
304
417
|
## Facet: design tokens and OS-aware themes
|
|
@@ -396,6 +509,55 @@ const b = {
|
|
|
396
509
|
|
|
397
510
|
---
|
|
398
511
|
|
|
512
|
+
## Highlight filter
|
|
513
|
+
|
|
514
|
+
`import 'apexcharts/features/highlight-filter'` *(7.9)*: **Tier 2** (not in the default bundle; script tag `dist/features/highlight-filter.js`, or the full bundle) and **premium**. It watermarks only while a render draws parts: loading the feature, or drawing a chart with no parts, never does.
|
|
515
|
+
|
|
516
|
+
Each value is drawn faded at its whole, with a part of it solid in front, from the same baseline and in the same slot: what a dashboard shows when a pick elsewhere leaves part of every value behind. The part travels with the data, as `highlightData` on a series (parallel to `data`, `null` where a datum has none) or `highlight` on a point (`{ x, y, highlight }`, which wins), so a pick and a clear are ordinary updates. A part may exceed its whole (an average) or have the other sign. Parts alone switch it on; every option is optional.
|
|
517
|
+
|
|
518
|
+
```js
|
|
519
|
+
import ApexCharts from 'apexcharts'
|
|
520
|
+
import 'apexcharts/features/highlight-filter'
|
|
521
|
+
|
|
522
|
+
const chart = new ApexCharts(el, {
|
|
523
|
+
chart: { type: 'bar' },
|
|
524
|
+
series: [{ name: 'Units', data: [34, 43, 66], highlightData: [26, null, 50] }],
|
|
525
|
+
xaxis: { categories: ['2015', '2016', '2017'] },
|
|
526
|
+
})
|
|
527
|
+
await chart.render()
|
|
528
|
+
|
|
529
|
+
// A new pick is an updateSeries() with new parts, or the helpers:
|
|
530
|
+
await chart.highlightFilter.set([[8, 14, 16]]) // one row per series
|
|
531
|
+
await chart.highlightFilter.clear() // the plain chart again
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
A pie, donut, polarArea, radialBar or gauge has no per-datum slot for a part, so give one per slice or ring in `highlightFilter.data` (a `highlight` on a slice's own `{ x, y }` point wins). A nested treemap takes `highlight` on each leaf and ignores `highlightData` with a warning.
|
|
535
|
+
|
|
536
|
+
| Option | Default | Notes |
|
|
537
|
+
|---|---|---|
|
|
538
|
+
| `enabled` | `true` | `false` keeps the parts in the data but draws the chart as usual. |
|
|
539
|
+
| `data` | none | Circles only: one part per slice or ring. Ignored, with a warning, while its length differs from the slice count. |
|
|
540
|
+
| `fadeOpacity` | `0.2` | Opacity of the faded whole. |
|
|
541
|
+
| `outline` | `{ width: 1, opacity: 1 }` | Keeps a faded whole readable; `width: 0` for none. |
|
|
542
|
+
| `enter` | `'whole'` | First pick: each part starts as its whole and drains (or grows) to the part. `'baseline'` rises from the baseline. |
|
|
543
|
+
| `axis` | `'extend'` | A part past the value axis stretches the axis; `'clamp'` keeps the axis the wholes set. |
|
|
544
|
+
| `dataLabels` | `{ value: 'part', total: 'part' }` | Each `'part'` or `'whole'`. `total` is the stack total and the donut's centre total. |
|
|
545
|
+
| `tooltip` | `{ show: true, share: false }` | Each row reads "part / whole"; `share` appends the part's percentage; `formatter(part, whole, opts)` returns the row's value text instead (plain text or HTML); the series name stays. |
|
|
546
|
+
|
|
547
|
+
Per type:
|
|
548
|
+
|
|
549
|
+
- `line.dashArray` (`4`): a line chart draws the whole dashed at full strength, with the part solid over it.
|
|
550
|
+
- `pie.encoding` (`'radius'`): how a part's share sets its radius on pie and donut; `'area'` makes the part's area its share. polarArea follows its own value scale.
|
|
551
|
+
- `radialBar.indicator`: `'arc'` when unset (the part as a solid arc in front of its faded whole), except `'needle'` on a gauge with `plotOptions.radialBar.shape: 'needle'`. `'lanes'` splits each ring into an outer whole lane and an inner part lane, for a part that can exceed its whole (`lanes.opacity`, default 0.45; the word on the whole lane's tooltip row is the locale's `options.highlightFilter.part`). `needle: { color, length, baseWidth, tipWidth, offsetY }` falls back to `plotOptions.radialBar.needle`.
|
|
552
|
+
|
|
553
|
+
**Where it draws.** Column and bar (grouped, horizontal, distributed, negative values, stacked including 100% and groups), funnel and pyramid, line and area (every curve, stacked area too), pie, donut, polarArea, radialBar and gauge, and treemap (flat and nested). Any other type, mixed-type charts, range series, histograms, and stacked charts over more than one y axis or a logarithmic one warn once and draw as usual. `highlightData` cannot follow `chart.dataReducer` or `chart.streaming` and warns there: put the part on each point instead.
|
|
554
|
+
|
|
555
|
+
**API and event.** `chart.highlightFilter` is `{ isActive(), valueAt(seriesIndex, dataPointIndex?), set(parts, opts?), clear(opts?) }`, or `null` without the feature (parts are then ignored with one console warning naming the import). `set` takes one row per series, one value per slice or ring on a circle, or a function of the datum, and resolves when the update is drawn. `chart.events.highlightFilterChanged(chart, { active, phase })` fires once that render is drawn, with `phase` `'enter'`, `'update'` or `'clear'`. Slice and tile label formatters (pie, donut, polarArea, treemap) and the donut and radialBar centre value and total formatters receive `opts.highlight` (`{ value, total, share, overflow }`). In `tooltip.custom`, read the part with `opts.ctx.highlightFilter.valueAt(opts.seriesIndex, opts.dataPointIndex)`.
|
|
556
|
+
|
|
557
|
+
**Drilldown.** A drill, either way, drops the parts from the level it shows, including any written into a `drilldown.series` entry, and reports `'clear'` if parts were on screen. Send the pick for the new level with `chart.highlightFilter.set()`.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
399
561
|
## Ink: direct-manipulation annotation authoring
|
|
400
562
|
|
|
401
563
|
`import 'apexcharts/features/ink'`: **Tier 2** (not in the default bundle) and **premium**.
|
|
@@ -537,13 +699,14 @@ const options = { chart: { streaming: { enabled: true, maxPoints: 100000 } } }
|
|
|
537
699
|
|
|
538
700
|
## Drilldown: hierarchical drill-down
|
|
539
701
|
|
|
540
|
-
`import 'apexcharts/features/drilldown'
|
|
702
|
+
`import 'apexcharts/features/drilldown'`: **Tier 2 since 8.0** (no longer in the default bundle; script tag `dist/features/drilldown.js`, or the full bundle). Free. `apexcharts/features/morph`, for animated cross-type transitions, is Tier 1 and already in the default bundle. Without the drilldown import, a chart with `drilldown.enabled` warns once and draws its root level, which never navigates, and `chart.drillDown()` / `drillUp()` / `drillToRoot()` / `clearDrilldownCache()` throw.
|
|
541
703
|
|
|
542
704
|
Data points reference a child level via a `drilldown` id; clicking drills in, with an optional breadcrumb. Since **v6.9** drilldown also works on **line and area** charts, and levels can be resolved **async** against a backend.
|
|
543
705
|
|
|
544
706
|
```js
|
|
545
|
-
import 'apexcharts
|
|
546
|
-
import 'apexcharts/features/
|
|
707
|
+
import ApexCharts from 'apexcharts'
|
|
708
|
+
import 'apexcharts/features/drilldown' // Tier 2 since 8.0
|
|
709
|
+
import 'apexcharts/features/morph' // animated type morphs; already in the default bundle
|
|
547
710
|
|
|
548
711
|
const options = {
|
|
549
712
|
series: [{ data: [
|
|
@@ -563,7 +726,8 @@ const options = {
|
|
|
563
726
|
// false disables it. role="status", aria-live="polite",
|
|
564
727
|
// spinner flattens to a pulse under prefers-reduced-motion
|
|
565
728
|
cache: true, // (v6.9) cache onDrillDown results by id (default true);
|
|
566
|
-
// clear with the
|
|
729
|
+
// clear with chart.clearDrilldownCache(id?), the public
|
|
730
|
+
// typed method (it delegates to the module's clearCache())
|
|
567
731
|
// (v6.9) line/area only: the dot marking a drillable point when the chart
|
|
568
732
|
// draws no markers. Only drillable points get one, so it reads as "these open".
|
|
569
733
|
marker: { show: true, size: 6, shape: 'circle', fillColor: undefined, strokeColor: '#fff' },
|
|
@@ -585,6 +749,8 @@ chart.drillToRoot()
|
|
|
585
749
|
|
|
586
750
|
**Async failure semantics (v6.9):** a failed fetch never strands the view. On a throw, a rejection, or a resolver returning something without a `data` 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.
|
|
587
751
|
|
|
752
|
+
*(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
|
+
|
|
588
754
|
---
|
|
589
755
|
|
|
590
756
|
## Stats: raw-sample statistics (6.9.0)
|
|
@@ -595,9 +761,9 @@ Free. The statistics behind three things, kept out of core so they cost nothing
|
|
|
595
761
|
|
|
596
762
|
- **Histogram binning**: `chart.type: 'histogram'` bins raw observations (the `apexcharts/histogram` entry includes this feature automatically).
|
|
597
763
|
- **Raw samples for boxPlot and violin**: a datum supplying `points: [number]` instead of a summary `y` gets its quartiles (R type 7) or KDE density computed.
|
|
598
|
-
- **`chart.rowSeries(opts?)`**: returns the rows behind the chart's marks as a unit-chart series (one cluster per mark), or `null` when the type has no row source. `chart.updateOptions({ chart: { type: 'unit' }, series: chart.rowSeries() })` opens a summary into its observations; with the `morph` feature loaded each dot leaves from the part of the mark that stood for it.
|
|
764
|
+
- **`chart.rowSeries(opts?)`**: returns the rows behind the chart's marks as a unit-chart series (one cluster per mark), or `null` when the type has no row source. `chart.updateOptions({ chart: { type: 'unit' }, series: chart.rowSeries() })` opens a summary into its observations; with the `morph` feature loaded each dot leaves from the part of the mark that stood for it. Since 8.0 `unit` is Tier 2, so add `import 'apexcharts/unit'` (or `dist/unit.js`, or the full bundle) first. Without it the update is refused with a console error and the chart stays as it was.
|
|
599
765
|
|
|
600
|
-
Full data shapes and options are in `references/financial-charts.md`. The
|
|
766
|
+
Full data shapes and options are in `references/financial-charts.md`. The default `apexcharts` bundle includes it.
|
|
601
767
|
|
|
602
768
|
---
|
|
603
769
|
|
|
@@ -631,9 +797,9 @@ const options = {
|
|
|
631
797
|
|
|
632
798
|
## Common Pitfalls
|
|
633
799
|
|
|
634
|
-
1. **Assuming the
|
|
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 `streamgraph`, 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`.
|
|
635
801
|
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>'`.
|
|
636
|
-
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).
|
|
802
|
+
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`.
|
|
637
803
|
4. **Using `api.zeroY` in a custom mark**: it does not exist. Use `ctx.scales.y(0)` for the baseline.
|
|
638
804
|
5. **Expecting `mode: 'filter'` on `chart.link` without records**: highlight mode needs `chart.selection.enabled: true`; the crossfilter engine needs `ApexCharts.crossfilter({ id, records })` or a `dimension` extractor.
|
|
639
805
|
6. **Two different `largeDatasetThreshold` options.** `chart.animations.largeDatasetThreshold` (default 1000) skips update animations; `markers.largeDatasetThreshold` *(v7.0, default 0 = off)* batches a series' markers into one path. Neither lives on `chart` directly.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- **Candlestick** (`'candlestick'`) — OHLC (Open, High, Low, Close) financial chart
|
|
6
6
|
- **Box Plot** (`'boxPlot'`) — Statistical distribution chart showing min, Q1, median, Q3, max
|
|
7
|
-
- **Violin** (`'violin'`, **new in v6**): Statistical distribution chart showing a density curve per category, optionally with the raw sample points overlaid as jitter
|
|
7
|
+
- **Violin** (`'violin'`, **new in v6, Tier 2 since v8.0**): Statistical distribution chart showing a density curve per category, optionally with the raw sample points overlaid as jitter
|
|
8
8
|
- **Histogram** (`'histogram'`, **new in v6.9**): Bins raw observations into columns; the series carries the sample, the chart does the aggregating
|
|
9
9
|
- **Raincloud** (`'raincloud'`, **new in v7.1, premium, Tier 2**): A distribution shown three ways at once: a half-violin for the shape, a box for the summary, and the observations themselves as "rain" underneath
|
|
10
10
|
|
|
@@ -15,14 +15,19 @@ import ApexCharts from 'apexcharts/candlestick'
|
|
|
15
15
|
// Registers: candlestick, boxPlot
|
|
16
16
|
// Alias: apexcharts/boxPlot
|
|
17
17
|
|
|
18
|
-
import ApexCharts from 'apexcharts/violin'
|
|
19
|
-
// Registers: violin (separate entry point, new in v6)
|
|
20
|
-
|
|
21
18
|
import ApexCharts from 'apexcharts/histogram'
|
|
22
19
|
// Registers: histogram (v6.9), the bar engine plus the stats feature
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
//
|
|
21
|
+
// violin is Tier 2 since v8.0 and raincloud since v7.1: neither is in the default bundle.
|
|
22
|
+
// Add the entry next to the default bundle:
|
|
23
|
+
import ApexCharts from 'apexcharts'
|
|
24
|
+
import 'apexcharts/violin' // Registers: violin (new in v6)
|
|
25
|
+
import 'apexcharts/raincloud' // Registers: raincloud (v7.1), the violin engine plus the raincloud feature
|
|
26
|
+
|
|
27
|
+
// Tree-shaking: violin and raincloud draw on the bar renderer without
|
|
28
|
+
// bundling one, so pair them with apexcharts/bar
|
|
29
|
+
import ApexCharts from 'apexcharts/bar'
|
|
30
|
+
import 'apexcharts/violin' // or 'apexcharts/raincloud'
|
|
26
31
|
|
|
27
32
|
// The statistics (histogram binning, boxPlot/violin raw-sample summaries,
|
|
28
33
|
// rowSeries()) live behind one optional feature. apexcharts/histogram already
|
|
@@ -30,9 +35,11 @@ import ApexCharts from 'apexcharts/raincloud'
|
|
|
30
35
|
import 'apexcharts/features/stats'
|
|
31
36
|
```
|
|
32
37
|
|
|
33
|
-
**⚠️
|
|
38
|
+
**⚠️ Violin is Tier 2 since v8.0.** `import ApexCharts from 'apexcharts'` no longer registers it, so a `chart.type: 'violin'` chart draws nothing and the console names the import. Add `import 'apexcharts/violin'` (script tag: `dist/violin.js`), or use the full bundle (`apexcharts/full`, `dist/apexcharts.full.min.js`). Plain violins stay free.
|
|
39
|
+
|
|
40
|
+
**⚠️ Raincloud is Tier 2 (v7.1).** Since v8.0 the default bundle carries neither the raincloud feature nor the violin renderer it draws through. Next to `import ApexCharts from 'apexcharts'` add `import 'apexcharts/raincloud'`, which brings both; `apexcharts/features/raincloud` alone is enough only where violin is already registered. Script tag: load `dist/violin.js`, then `dist/features/raincloud.js`. Or use the full bundle (`apexcharts/full`, `dist/apexcharts.full.min.js`), which has both. On the lean core also import `apexcharts/bar`. It is also premium, so it renders an `APEXCHARTS` watermark until an entitled license is set.
|
|
34
41
|
|
|
35
|
-
**Raw samples (v6.9):** boxPlot, violin, and histogram can all take the raw observations and compute the statistics themselves (quartiles for boxPlot, KDE density for violin, bin counts for histogram). Precomputed summaries keep working exactly as before.
|
|
42
|
+
**Raw samples (v6.9):** boxPlot, violin, and histogram can all take the raw observations and compute the statistics themselves (quartiles for boxPlot, KDE density for violin, bin counts for histogram). Precomputed summaries keep working exactly as before. The default `apexcharts` bundle (and the full bundle) always has the stats feature; with tree-shaking entries it must be imported (without it, a raw-sample boxPlot/violin draws nothing, with a console warning naming the import since v8.0, and a histogram warns and draws nothing).
|
|
36
43
|
|
|
37
44
|
---
|
|
38
45
|
|
|
@@ -125,6 +132,8 @@ Each point is `{ x, y: { density, points } }`:
|
|
|
125
132
|
- `points` (optional): a flat array of raw observations, rendered as jitter dots.
|
|
126
133
|
|
|
127
134
|
```js
|
|
135
|
+
import 'apexcharts/violin' // Tier 2 since v8.0: not in the default bundle
|
|
136
|
+
|
|
128
137
|
{
|
|
129
138
|
chart: { type: 'violin', height: 420 },
|
|
130
139
|
series: [{
|
|
@@ -161,6 +170,8 @@ Each point is `{ x, y: { density, points } }`:
|
|
|
161
170
|
A datum may instead supply only the raw observations (in `points`, no `y`) and the library derives the density itself via kernel density estimation. Requires `apexcharts/features/stats` when tree-shaking. `plotOptions.violin.kde` tunes the estimation; it is ignored when a precomputed `density` profile is given.
|
|
162
171
|
|
|
163
172
|
```js
|
|
173
|
+
import 'apexcharts/violin' // Tier 2 since v8.0: not in the default bundle
|
|
174
|
+
|
|
164
175
|
{
|
|
165
176
|
chart: { type: 'violin', height: 420 },
|
|
166
177
|
series: [{
|
|
@@ -196,7 +207,7 @@ plotOptions: {
|
|
|
196
207
|
|
|
197
208
|
### Histogram (v6.9)
|
|
198
209
|
|
|
199
|
-
The series carries **raw observations** (a flat number array, or `{ y }` objects), one number per event; the chart chooses the bin width and counts them. It renders through the bar pathway (like funnel
|
|
210
|
+
The series carries **raw observations** (a flat number array, or `{ y }` objects), one number per event; the chart chooses the bin width and counts them. It renders through the bar pathway (like funnel and pyramid), so stacking, zoom, export, and animation all work on the bins. Import from `apexcharts/histogram`, or add `import 'apexcharts/features/stats'` alongside `apexcharts/bar`; the default `apexcharts` bundle already includes it. Without the stats feature the chart warns and draws nothing.
|
|
200
211
|
|
|
201
212
|
```js
|
|
202
213
|
{
|
|
@@ -228,7 +239,7 @@ The series carries **raw observations** (a flat number array, or `{ y }` objects
|
|
|
228
239
|
|
|
229
240
|
```js
|
|
230
241
|
import ApexCharts from 'apexcharts'
|
|
231
|
-
import 'apexcharts/raincloud' // Tier 2:
|
|
242
|
+
import 'apexcharts/raincloud' // Tier 2: not in the default bundle (apexcharts/full already has it)
|
|
232
243
|
|
|
233
244
|
new ApexCharts(el, {
|
|
234
245
|
chart: { type: 'raincloud', height: 350 },
|
|
@@ -286,9 +297,12 @@ The rain **is** the outlier display, so the box draws no outlier dots of its own
|
|
|
286
297
|
A histogram bin, a box, and a violin all stand for rows the chart is already holding. `chart.rowSeries()` returns them as a unit-chart series (one cluster per mark, one datum per row), so a summary can be opened into its observations:
|
|
287
298
|
|
|
288
299
|
```js
|
|
300
|
+
import 'apexcharts/unit' // Tier 2 since v8.0: the target type must be loaded
|
|
289
301
|
chart.updateOptions({ chart: { type: 'unit' }, series: chart.rowSeries() })
|
|
290
302
|
```
|
|
291
303
|
|
|
304
|
+
Since v8.0 the unit type is not in the default bundle, so load it first (`apexcharts/unit`, `dist/unit.js`, or the full bundle). Without it the update is refused (the promise rejects and the console names the import) and the chart stays as it was.
|
|
305
|
+
|
|
292
306
|
Returns `null` when the current type has no row source or the stats feature is not loaded. `chart.rowSeries({ maxRows })` caps the dots produced (default 3000); past the cap every cluster is thinned by one shared stride so relative sizes survive. With the `morph` feature loaded, each dot animates out of the part of the mark that stood for it.
|
|
293
307
|
|
|
294
308
|
---
|
|
@@ -324,6 +338,8 @@ plotOptions: {
|
|
|
324
338
|
}
|
|
325
339
|
```
|
|
326
340
|
|
|
341
|
+
**Updates animate (v7.9):** on `updateSeries()` each box morphs from its previous shape. Set `chart: { animations: { dynamicAnimation: { enabled: false } } }` to snap instead.
|
|
342
|
+
|
|
327
343
|
---
|
|
328
344
|
|
|
329
345
|
## Complete Working Example — Candlestick Chart
|
|
@@ -382,7 +398,7 @@ plotOptions: {
|
|
|
382
398
|
7. **Violin orientation set on the wrong namespace**: horizontal violins and per-violin colors come from `plotOptions.bar` (`horizontal`, `distributed`), while `bandwidthScale`, `kde`, `normalize`, and `points` live under `plotOptions.violin`.
|
|
383
399
|
8. **Feeding a histogram pre-binned counts**: the series must carry raw observations. If you already have counts per bucket, use a `bar` chart; a histogram would bin your counts as if they were measurements.
|
|
384
400
|
9. **`whiskers: 'tukey'` on a precomputed boxPlot summary**: `plotOptions.boxPlot.whiskers` only applies when the summary is derived from `points`. A five-number `y` is drawn exactly as given.
|
|
385
|
-
10. **Raw samples with tree-shaking but no stats feature**: `apexcharts/candlestick
|
|
386
|
-
11. **Expecting `
|
|
401
|
+
10. **Raw samples with tree-shaking but no stats feature**: `apexcharts/candlestick`, and `apexcharts/bar` plus `apexcharts/violin`, cannot summarize `points`. Add `import 'apexcharts/features/stats'` (the `apexcharts/histogram` entry and the default bundle already include it). Since v8.0 the console names the missing import.
|
|
402
|
+
11. **Expecting `violin` or `raincloud` on the default bundle** *(v8.0)*: `import ApexCharts from 'apexcharts'` registers neither, so the chart draws nothing and the console reports `chart type "violin" is not registered` (for a raincloud, `chart type "raincloud" is not registered (it draws through "violin")`) with the import to add. That is the same failure an unregistered `icicle` gives. Add `import 'apexcharts/violin'` for a plain violin or `import 'apexcharts/raincloud'` for a raincloud, or use the full bundle (`apexcharts/full`).
|
|
387
403
|
12. **Looking for `plotOptions.raincloud`**: there is none. Raincloud is a preset over the violin engine, so configure it through `plotOptions.violin` (`side`, `box`, `points`, `kde`, `normalize`).
|
|
388
404
|
13. **Giving a raincloud a `y`**: it takes the raw sample per category: `data: [{ x, points: [number] }]`. A precomputed `y.summary` is honored for the box, but the density and the rain need the observations.
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
|
|
11
11
|
**Important:** All wrappers require `apexcharts` as a peer dependency. Install both packages.
|
|
12
12
|
|
|
13
|
+
**With apexcharts 8**, use ng-apexcharts 3.2.0 or later (Angular 20+): 3.1.x accepts apexcharts 6 or 7 only, so npm reports a peer conflict. react-apexcharts (2.1.1) and vue3-apexcharts (1.11.2) accept any apexcharts from 5.10 up, and vue-apexcharts (Vue 2) any from 4.0.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Opt-in chart types and features (apexcharts 8)
|
|
18
|
+
|
|
19
|
+
The wrappers' standard components load the default ApexCharts bundle, which since 8.0 leaves out some chart types and features (see `references/tree-shaking.md`). Until the app imports the add-on, a wrapper chart of type `unit`, `waffle`, `sunburst`, `violin`, `icicle` or `raincloud` fails to render, and `waterfall`, `dumbbell` or `streamgraph` draws an empty plot. Import it once anywhere in the app (`main.ts`, or the component file): it registers on the ApexCharts the wrapper uses.
|
|
20
|
+
|
|
21
|
+
| You use | Add once |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `unit`/`waffle`, `sunburst`, `violin`, `icicle` | `import 'apexcharts/unit'` (or `/sunburst`, `/violin`, `/icicle`) |
|
|
24
|
+
| `raincloud` | `import 'apexcharts/raincloud'` |
|
|
25
|
+
| `waterfall`, `dumbbell`, `streamgraph`, drilldown or another Tier 2 feature | `import 'apexcharts/features/<name>'` (`highlightFilter` is `features/highlight-filter`) |
|
|
26
|
+
| Everything | `import 'apexcharts/full'`, which reuses the default bundle the wrapper already loads |
|
|
27
|
+
|
|
28
|
+
```jsx
|
|
29
|
+
import Chart from 'react-apexcharts'
|
|
30
|
+
import 'apexcharts/sunburst' // once per app
|
|
31
|
+
|
|
32
|
+
export default function Breakdown({ options, series }) {
|
|
33
|
+
return <Chart type="sunburst" options={options} series={series} height={350} />
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
13
37
|
---
|
|
14
38
|
|
|
15
39
|
## React
|
|
@@ -218,7 +242,7 @@ updateChart() {
|
|
|
218
242
|
<div id="chart"></div>
|
|
219
243
|
|
|
220
244
|
<!-- CDN -->
|
|
221
|
-
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
|
|
245
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8/dist/apexcharts.min.js"></script>
|
|
222
246
|
|
|
223
247
|
<script>
|
|
224
248
|
const options = {
|
|
@@ -234,18 +258,24 @@ updateChart() {
|
|
|
234
258
|
|
|
235
259
|
### CDN Links
|
|
236
260
|
|
|
261
|
+
```html
|
|
262
|
+
<!-- default bundle -->
|
|
263
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8/dist/apexcharts.min.js"></script>
|
|
264
|
+
<!-- one add-on next to it: an opt-in chart type -->
|
|
265
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8/dist/sunburst.js"></script>
|
|
266
|
+
|
|
267
|
+
<!-- or the full bundle: every chart type and feature, no add-ons -->
|
|
268
|
+
<script src="https://cdn.jsdelivr.net/npm/apexcharts@8/dist/apexcharts.full.min.js"></script>
|
|
237
269
|
```
|
|
238
|
-
|
|
239
|
-
https://cdn.jsdelivr.net/npm/apexcharts@
|
|
240
|
-
https://unpkg.com/apexcharts
|
|
241
|
-
```
|
|
270
|
+
|
|
271
|
+
Pin the major: the unversioned URLs (`https://cdn.jsdelivr.net/npm/apexcharts`, `https://unpkg.com/apexcharts`) moved to 8.0 on its release. Use `apexcharts@7` to stay on 7. The other add-ons are `dist/unit.js`, `dist/violin.js`, `dist/icicle.js` and `dist/features/<name>.js`, and may load before or after the main script.
|
|
242
272
|
|
|
243
273
|
---
|
|
244
274
|
|
|
245
275
|
## Common Framework Pitfalls
|
|
246
276
|
|
|
247
277
|
1. **Missing peer dependency** — `react-apexcharts`, `vue3-apexcharts`, and `ng-apexcharts` all require `apexcharts` as a separate dependency.
|
|
248
|
-
2. **SSR with wrapper components
|
|
278
|
+
2. **SSR with wrapper components**: the standard components access `window`/`document` and can crash in SSR. Use dynamic imports with `{ ssr: false }`, the native SSR API, or the wrapper's SSR components: `react-apexcharts/server`, vue3-apexcharts `<apexchart-server>` and `<apexchart-hydrate>` (1.11.2 or later, which render with your installed apexcharts), ng-apexcharts `<apx-chart-ssr>` and `<apx-chart-hydrate>`. They load `apexcharts/ssr`, so with apexcharts 8 a Tier 2 type needs its opt-in import on the server too. For React hydration call `apexcharts/ssr` directly: `react-apexcharts/hydrate` (2.1.1) loads `apexcharts/client`, which has no `hydrate()`.
|
|
249
279
|
3. **Not destroying on unmount (vanilla API in React/Vue)** — causes memory leaks and duplicate charts. The official wrappers handle this automatically.
|
|
250
280
|
4. **Mutating config objects in place (Vue)** — deep mutations may not trigger reactivity. Replace the entire object or use `ref` at the right level.
|
|
251
281
|
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.
|