---
title: Contracts — ChartAdapter and IconPreset
description: The two interfaces WireKit publishes for you to implement — a chart library adapter and an icon preset — and what each method is for.
visibility: guest
draft: false
---

# Contracts — `ChartAdapter` and `IconPreset`

Most of WireKit is extended by composing components and overriding tokens. Two things are
extended by implementing an **interface** instead, because the package has to call your code
rather than the other way round: adding a chart library it does not ship, and adding a set of
icon aliases.

Both live in `Pushery\WireKit\Contracts`. Neither is abstract-class-based — they are plain
interfaces with no base to inherit, so nothing in your implementation is inherited by accident.

## `ChartAdapter` — teach the chart component a new library

WireKit ships adapters for Chart.js and ApexCharts and bundles neither library. An adapter is
the translation layer between the `<x-wirekit::chart>` API and one library's option shape.

ApexCharts is **not MIT-licensed** — the free Community License covers organizations under
$2 million USD annual revenue, and above that a Commercial License is required. That applies to
the library you install, never to WireKit's adapter glue, which is MIT either way. See
[the License section on the Chart overview](/components/chart#license-apexcharts-only) or
[apexcharts.com/license](https://apexcharts.com/license/) for the canonical text.

```php
use Pushery\WireKit\Contracts\ChartAdapter;

final class MyChartAdapter implements ChartAdapter
{
    // 1. Stable slug used in error messages and config comparison. It must NOT change
    //    across patch releases — a developer's config names it.
    public function name(): string
    {
        return 'my-charts';
    }

    // 2. Scripts the page needs in <head>. Return an empty array when the developer
    //    installs the library themselves, which is what both shipped adapters do.
    public function scripts(): array
    {
        return [];
    }

    // 3. Translate WireKit's labels + datasets into the library's own data shape.
    public function normalizeData(string $type, array $labels, array $datasets): array
    {
        return ['labels' => $labels, 'datasets' => $datasets];
    }

    // 4. Per-type option defaults — tooltips, legends, axes.
    public function defaultOptions(string $type): array
    {
        return [];
    }

    // 5. The Alpine factory that mounts it, and what that factory renders into.
    public function alpineComponent(): string
    {
        return 'myChart';
    }

    public function rendersTo(): string
    {
        return 'canvas';
    }

    // 6. Every type this adapter accepts. `<x-wirekit::chart type="…">` is validated
    //    against it, so a type missing here is rejected before your code runs.
    public function supportedTypes(): array
    {
        return ['bar', 'line'];
    }
}
```

Register it by pointing the chart config at your class:

```php
// config/wirekit.php
'charts' => [
    'library' => \App\Charts\MyChartAdapter::class,
],
```

::: warning The manager checks the type before it constructs
`ChartManager` verifies your class implements `ChartAdapter` **before** instantiating it, so a
class that merely looks adapter-shaped fails with a clear message rather than a fatal partway
through a render.
:::

## `IconPreset` — add a set of icon aliases

An icon preset maps WireKit's semantic alias names (`close`, `search`, `chevron-down`) onto one
icon family's identifiers, so a component can ask for a concept and get whatever the active
family calls it.

```php
use Pushery\WireKit\Contracts\IconPreset;

final class MyIconPreset implements IconPreset
{
    // 1. alias => Blade Icon identifier.
    public function icons(): array
    {
        return [
            'close' => 'my-x-mark',
            'search' => 'my-magnifier',
        ];
    }

    // 2. The composer package that must be installed for those identifiers to resolve.
    //    Surfaced by `wirekit:doctor` when it is missing.
    public function requires(): string
    {
        return 'vendor/my-icons';
    }
}
```

```php
// config/wirekit.php — presets stack, later entries win, and a developer-level
// alias overrides all of them.
'icons' => [
    'presets' => ['heroicons', \App\Icons\MyIconPreset::class],
],
```

::: info Base presets carry the whole alias set; extension presets need not
The four base presets — heroicons, lucide, phosphor, tabler — must all define the same standard
aliases, and a test enforces that parity. A **stackable** preset like your own may define as few
as one: it is layered over a base rather than replacing it.
:::

::: warning An alias is only added when EVERY shipped preset has a genuine glyph for it
This is a house rule about the aliases WireKit itself ships, and it applies the moment you
propose one upstream: an alias that resolves in three families and substitutes something merely
similar in the fourth reads as a contract and is not one. Switching families then silently draws
the wrong glyph — nothing errors, nothing logs, and the icon is simply not the one the component
asked for. Your own preset is yours to shape; the shared alias set is not.
:::

## See Also

- [Chart](../components/chart.md) — the component an adapter serves
- [Icon](../components/icon.md) — presets, aliases and the shipped families
- [ComponentRegistry](component-registry.md) — discovering components from PHP
