# Migrating from ApexCharts 4.x

> WestCoast Charts 1.1.5, release, public Core release, on npm. HTML: https://westcoast-charts.com/docs/migration-from-apexcharts/ · Index for agents: https://westcoast-charts.com/llms.txt · Source: library guide, commit 95f093ba

WestCoast Charts started from the MIT-licensed ApexCharts 4.7.0 source and keeps an
**ApexCharts-style configuration model** for familiar options, methods and events.
This is not a guarantee of unchanged behaviour for every application. Review the
differences in themes, accessibility, text escaping, sanitization and validation below,
then test your actual charts before switching.

> ApexCharts is a trademark of its owner. WestCoast Charts is an independent project by West Coast
> Software and is not affiliated with, sponsored or endorsed by the owner of ApexCharts. The name is used
> here only to describe compatibility and to credit the origin of the code (see `LICENSE` and `NOTICE`).

**Which versions?** This guide is written for code that targets ApexCharts **4.x** (4.0 to 4.7). Options
that first appeared in later ApexCharts versions are not part of WestCoast Charts.

- [The switch in three steps](#the-switch-in-three-steps)
- [What stays the same](#what-stays-the-same)
- [What behaves differently](#what-behaves-differently) – read this before you ship
- [What is new](#what-is-new)
- [Checklist](#checklist)

## The switch in three steps

**1. Replace the package.**

```sh
npm uninstall apexcharts
npm install west-coast-charts@1.1.5
```

**2. Change the import.** The default export is the chart class. It is also exported under the name
`ApexCharts`, so the rest of your code can keep the old identifier:

```js
// before: import ApexCharts from 'apexcharts'
import { ApexCharts } from 'west-coast-charts'

const chart = new ApexCharts(document.querySelector('#chart'), {
  chart: { type: 'area', height: 300 },
  series: [{ name: 'Sign-ups', data: [31, 40, 28, 51, 42, 109, 100] }],
  xaxis: { categories: ['W1', 'W2', 'W3', 'W4', 'W5', 'W6', 'W7'] },
})
await chart.render()
```

With script tags, swap the file. The bundle defines the global `WestCoastCharts` and also
`window.ApexCharts` when that global is still free, so inline code that says `new ApexCharts(...)`
keeps working:

```html
<!-- before: <script src=".../apexcharts.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/west-coast-charts@1.1.5/dist/west-coast-charts.min.js"></script>
<div id="chart"></div>
<script>
  new ApexCharts(document.querySelector('#chart'), {
    chart: { type: 'bar', height: 260 },
    series: [{ name: 'Tickets', data: [8, 13, 5, 21] }],
    xaxis: { categories: ['Mon', 'Tue', 'Wed', 'Thu'] },
  }).render()
</script>
```

**3. Decide about the look.** Charts use the new `coastal` theme preset by default (palette, typography,
spacing). To keep the 4.7.0 appearance pixel for pixel, select the `classic` preset, either per chart or
for every chart through the `window.Apex` global defaults, which work as before:

```js
import WestCoastCharts from 'west-coast-charts'

// every chart on the page
window.Apex = { theme: { preset: 'classic' } }

// or one chart
const chart = new WestCoastCharts(document.querySelector('#chart'), {
  theme: { preset: 'classic' },
  chart: { type: 'line', height: 260 },
  series: [{ name: 'Errors', data: [3, 1, 4, 1, 5] }],
})
await chart.render()
console.log(chart.w.globals.colors[0]) // '#008FFB', the 4.7.0 palette
```

Then run your test suite and go through [What behaves differently](#what-behaves-differently).

## What stays the same

| Area | Status |
| --- | --- |
| Options | Familiar 4.7.0 option names and structure; review the behaviour and default changes documented below |
| Chart types | All 4.7.0 types are in the core: line, area, bar/column, rangeBar, rangeArea, candlestick, boxPlot, scatter, bubble, heatmap, treemap, pie, donut, polarArea, radar, radialBar, mixed charts |
| Methods | `render`, `updateOptions`, `updateSeries`, `appendSeries`, `appendData`, `toggleSeries`, `showSeries`, `hideSeries`, `resetSeries`, `zoomX`, `toggleDataPointSelection`, `addXaxisAnnotation` and the other annotation methods, `dataURI`, `destroy`, and the static `exec`, `getChartByID`, `merge`, `initOnLoad` |
| Events | `chart.events.*` callbacks with the same arguments |
| Global defaults | `window.Apex` |
| Locales | The same locale objects and `chart.locales` / `chart.defaultLocale` |
| CSS | Every `apexcharts-*` class name stays, so your style overrides and test selectors keep matching. The root element also gets the class `wcc` |
| TypeScript | `ApexOptions` and all `Apex*` types are still exported |

The complete, generated list is in the [options reference](https://westcoast-charts.com/docs/reference/options/index.md) and the
[methods reference](https://westcoast-charts.com/docs/reference/methods/index.md).

## What behaves differently

These changes are deliberate: they fix security issues or crashes, or they add accessibility. Each one
names the setting that restores the 4.7.0 behaviour where one exists.

### 1. Default theme

New charts use the `coastal` preset. Use `theme: { preset: 'classic' }` for the old look
([step 3](#the-switch-in-three-steps)). Explicit colours, fonts and `theme.palette` settings are applied
on top of either preset, as before. See docs/THEMING.md (library repository).

### 2. HTML in labels, legends and tooltips

- Strings from **data and configuration** (series names, categories, labels, titles, annotation text,
  locale strings) are always drawn as **text**. A series named `<b>EU</b>` shows those characters instead
  of bold text.
- HTML returned by **your functions** (formatters, `tooltip.custom`, `legend.markers.customHTML`) and
  explicit markup options (toolbar icons, `customSVG`) is still allowed, but it passes through a
  sanitizer first. Event-handler attributes, `javascript:` URLs and scripts are removed.
- `chart.sanitizeHtml` controls this: `true` (default, built-in allow-list), a function
  `(html, { svg }) => string | Node` to plug in your own sanitizer such as DOMPurify, or `false` for raw
  `innerHTML` as in 4.7.0 (only for output you fully trust).
- When you build HTML from data in a formatter, escape the data with `WestCoastCharts.escapeHtml()`.

```js
import WestCoastCharts from 'west-coast-charts'

const chart = new WestCoastCharts(document.querySelector('#chart'), {
  chart: { type: 'line', height: 260 },
  series: [
    { name: 'eu-west', data: [12, 18, 15] },
    { name: 'us-east', data: [20, 14, 22] },
  ],
  legend: {
    show: true,
    // escape the data, keep your own markup; the onerror handler is stripped by the sanitizer
    formatter: (name) => `<b>${WestCoastCharts.escapeHtml(name)}</b><img src="x" onerror="alert(1)">`,
  },
})
await chart.render()
```

### 3. CSV export

`exportToCSV` neutralises spreadsheet formulas: text cells that start with `=`, `+`, `-`, `@`, tab or
carriage return get a leading `'`. Real numbers such as `-12.5` are left alone. Cells containing the
delimiter, quotes or line breaks are quoted (RFC 4180) instead of having characters removed. There is no
switch back; this closes a formula-injection hole.

### 4. Malformed options no longer throw

Inputs that made 4.7.0 throw a `TypeError`, for example `series: null`, `null` entries in `series`,
`data: null`, `xaxis.categories: null` or `annotations: null`, are treated as empty, in the constructor
and in every update method. If your code relied on a throw to detect bad data, validate the data
yourself instead. Valid options are passed through untouched.

```js
import WestCoastCharts from 'west-coast-charts'

const chart = new WestCoastCharts(document.querySelector('#chart'), {
  chart: { type: 'bar', height: 240 },
  series: null, // data not loaded yet: an empty chart instead of an exception
})
await chart.render()
await chart.updateSeries([{ name: 'Orders', data: [5, null, 9] }, null])
```

### 5. Accessibility is on by default

Every chart now adds:

- `tabindex="0"`, an ARIA accessible name and `<desc>` on the chart SVG, plus keyboard navigation (arrow keys, Home/End,
  Enter/Space, zoom and pan keys). Tab is never captured.
- a polite live region that announces the focused point, selection and zoom,
- a visually hidden data table for screen readers,
- `prefers-reduced-motion` support: animations are skipped for users who ask for less motion.

This changes the DOM: snapshot tests and selectors that count elements inside the chart container, or
tests of the page's tab order, can need an update. You can switch the parts off individually, but please
only do so when you provide the same information another way:

```js
import WestCoastCharts from 'west-coast-charts'

const chart = new WestCoastCharts(document.querySelector('#chart'), {
  chart: {
    type: 'line',
    height: 240,
    accessibility: {
      enabled: true,                      // master switch
      keyboard: { enabled: true },
      announcements: { enabled: true },
    },
    animations: { respectReducedMotion: true },
  },
  wcc: { a11y: { dataTable: false } },   // 'hidden' (default) | 'details' (visible) | false
  series: [{ name: 'Queue depth', data: [4, 9, 6, 12] }],
})
await chart.render()
```

Details: docs/ACCESSIBILITY.md (library repository).

### 6. Bundle size

The core is larger than ApexCharts 4.7.0 because the accessibility, security, theming and robustness
work above lives in it: 192,030 B against 152,686 B for `apexcharts.min.js` 4.7.0 (gzip level 9, measured
on integrate/v1 `d03e23b2`). Where the bytes go is documented in
docs/architecture/size-ledger.md (library repository). New chart types and features live in
separate entries, so they cost nothing unless you import them.

### 7. Unknown chart types fail loudly

If `chart.type` names a WestCoast Charts type whose entry is not loaded (for example `funnel` without
`west-coast-charts/types`), `render()` rejects with a message naming the import to add, and logs the same
hint. Types that existed in 4.7.0 are never affected.

### 8. Toolbar size in the new presets

The `coastal` preset (and the presets from `west-coast-charts/types/themes`) uses 28 × 28 px toolbar
buttons to meet the WCAG 2.5.8 target size. `classic` keeps the 4.7.0 20 px icons.

### 9. Browser support

The core still targets ES2018 engines (Chrome 60+, Edge 79+, Firefox 55+, Safari 11.1+). Optional feature
bundles and the premium bundle need ES2020; see
[Getting started](https://westcoast-charts.com/docs/getting-started/index.md#es-modules-commonjs-and-script-tags) and the browser table in the
repository README.

## What is new

Everything below is optional; none of it changes a 4.7.0 configuration.

| Addition | Where | Docs |
| --- | --- | --- |
| Theme presets `coastal` and `classic` in the core; `midnight`, `paper`, `accessible` and colour-vision palettes (`theme.accessibility.colorBlindMode`) | core, `west-coast-charts/types/themes` | THEMING.md (library repository) |
| 14 additional chart types: gauge, funnel/pyramid, waterfall, dumbbell, histogram, violin/raincloud, sunburst, icicle, streamgraph, unit/waffle, barRace, calendar, slope, beeswarm (plus nested treemaps and box plots from raw samples) | `west-coast-charts/types` or `west-coast-charts/types/<name>` | [options reference](https://westcoast-charts.com/docs/reference/options/index.md) |
| Keyboard navigation, announcements, data table, focus ring | core | ACCESSIBILITY.md (library repository) |
| Large-data rendering: dense-mark paths and line/area decimation (`wcc.performance`), optional canvas renderer | core (dense marks), `west-coast-charts/types/decimate`, `west-coast-charts/features/renderer-canvas` | [Performance and security](https://westcoast-charts.com/docs/performance-and-security/index.md) |
| Label readability (halo, pill, auto contrast) | `west-coast-charts/features/readability` | docs/features/readability.md (library repository) |
| Drill-down, linked charts, highlight and filter, undo history, narrative captions, perspectives, storyboards, trellis small multiples | `west-coast-charts/features/<name>` | `docs/features/` |
| Plugin API: `WestCoastCharts.use(plugin)` | core | docs/architecture/plugins.md (library repository) |
| `WestCoastCharts.escapeHtml`, `chart.sanitizeHtml`, Trusted Types policy `west-coast-charts` | core | [Performance and security](https://westcoast-charts.com/docs/performance-and-security/index.md#security) |
| Premium types: sankey, chord, gantt, tree, stock, map, marimekko, network, radialColumn | `west-coast-charts/premium` (licence key) | [Premium and licensing](https://westcoast-charts.com/docs/premium/index.md) |

## Checklist

- [ ] `apexcharts` replaced by `west-coast-charts` in `package.json` and in all imports or script tags
- [ ] Look decided: `coastal` (new default) or `theme: { preset: 'classic' }`
- [ ] Formatters that return HTML built from data use `WestCoastCharts.escapeHtml()`
- [ ] Series names or labels that contained intended HTML moved into a formatter
- [ ] Snapshot and DOM tests updated for the accessibility elements
- [ ] CSV consumers are fine with the `'` prefix on formula-like cells
- [ ] Code that relied on exceptions for bad configs now validates its data
- [ ] Content Security Policy checked ([Getting started](https://westcoast-charts.com/docs/getting-started/index.md#content-security-policy))
