
# Plugins personnalisés

Un plugin personnalisé est une classe PHP qui implémente `TailwindPHP\Plugin\PluginInterface`. Il reçoit une instance de `PluginAPI` et l’utilise pour enregistrer des utilitaires statiques et fonctionnels, des composants et des variantes. Une fois enregistré avec `registerPlugin()`, le plugin est résolu par son nom dans une directive `@plugin` — le même mécanisme qu’utilisent les plugins intégrés de typographie et de formulaires.

## `PluginInterface`

Implémentez trois méthodes :

```php
namespace TailwindPHP\Plugin;

interface PluginInterface
{
    public function getName(): string;
    public function __invoke(PluginAPI $api, array $options = []): void;
    public function getThemeExtensions(array $options = []): array;
}
```

- `getName()` renvoie l’identifiant utilisé dans `@plugin "..."`.
- `__invoke()` exécute le plugin et enregistre tous ses éléments via `$api`. Le tableau `$options` contient les valeurs du bloc `@plugin` CSS.
- `getThemeExtensions()` renvoie les espaces de noms du thème à fusionner avant la génération des utilitaires (renvoie `[]` s’il n’y en a aucun).

## Exemple

```php
use TailwindPHP\Plugin\PluginInterface;
use TailwindPHP\Plugin\PluginAPI;

class MyCustomPlugin implements PluginInterface
{
    public function getName(): string
    {
        return 'my-custom-plugin';
    }

    public function __invoke(PluginAPI $api, array $options = []): void
    {
        // Static utilities
        $api->addUtilities([
            '.btn' => [
                'padding' => '0.5rem 1rem',
                'border-radius' => '0.25rem',
                'font-weight' => '600',
            ],
            '.btn-primary' => [
                'background-color' => 'blue',
                'color' => 'white',
            ],
        ]);

        // Functional utilities (generates .gutter-sm, .gutter-md, .gutter-lg)
        $api->matchUtilities(
            [
                'gutter' => fn ($value) => ['padding-inline' => $value],
            ],
            ['values' => ['sm' => '1rem', 'md' => '2rem', 'lg' => '3rem']]
        );

        // Component classes (sorted into the components layer)
        $api->addComponents([
            '.card' => [
                'background-color' => 'white',
                'border-radius' => '0.5rem',
                'padding' => '1rem',
            ],
        ]);

        // Custom variant (see the note below the API reference)
        $api->addVariant('hocus', '&:hover, &:focus');

        // Read a theme value
        $primary = $api->theme('colors.blue.500', '#3b82f6');
    }

    public function getThemeExtensions(array $options = []): array
    {
        return []; // Return theme additions if needed
    }
}
```

## Référence de `PluginAPI`

Le API reprend le TailwindCSS du plugin API :

| Méthode | Signature | Rôle |
|--------|-----------|---------|
| `addBase` | `addBase(array $css): void` | Ajoute des styles à la couche de base. |
| `addUtilities` | `addUtilities(array $utilities, array $options = []): void` | Enregistre les classes d’utilitaires statiques indexées par sélecteur. |
| `matchUtilities` | `matchUtilities(array $utilities, array $options = []): void` | Enregistre des utilitaires fonctionnels ; `$options['values']` fournit la table des valeurs, `$options['supportsNegativeValues']` active les valeurs négatives. |
| `addComponents` | `addComponents(array $components, array $options = []): void` | Enregistre des classes de composants (couche des composants). |
| `matchComponents` | `matchComponents(array $components, array $options = []): void` | Enregistre des composants fonctionnels avec une table des valeurs. |
| `addVariant` | `addVariant(string $name, string\|array $variant): void` | Enregistre une variante statique à partir d’un sélecteur. |
| `matchVariant` | `matchVariant(string $name, callable $callback, array $options = []): void` | Enregistre une variante fonctionnelle ; `$options['values']` fournit la table des valeurs. |
| `theme` | `theme(string $path, mixed $defaultValue = null): mixed` | Lit une valeur de thème à partir d’un chemin en notation pointée (e.g. `colors.blue.500`). |
| `config` | `config(?string $path = null, mixed $defaultValue = null): mixed` | Lit une valeur de configuration à partir d’un chemin en notation pointée, ou toute la configuration si `$path` est null. |
| `prefix` | `prefix(string $className): string` | Applique le préfixe configuré à un nom de classe. |

La fonction de rappel transmise à `matchUtilities`, `matchComponents` et `matchVariant` reçoit la valeur et un tableau en second argument contenant une clé `modifier`.

Choisissez des noms d’utilitaires que le cœur de Tailwind n’utilise pas déjà. Lorsqu’un utilitaire de plugin partage le nom d’un utilitaire central (par exemple `tab-*`, utilisé par le cœur de Tailwind pour `tab-size` depuis v4.3), les deux déclarations aboutissent dans la même règle et celle du cœur vient en dernier : elle l’emporte. Un utilitaire de plugin `tab-4` associé à `7` produit donc toujours `tab-size: 4`.

> **Problème connu :** les variantes enregistrées avec `addVariant()`, ainsi que les variantes par valeur enregistrées par `matchVariant()`, ne sont pas appliquées dans la version actuelle. `hocus:flex` de l’exemple ci-dessus est compilé en `.hocus\:flex { display: flex; }` sans sélecteur `:hover`/`:focus` ([#10](https://github.com/inline0/tailwindphp/issues/10)). En attendant le correctif, définissez la variante dans CSS avec [`@custom-variant`](https://tailwindphp.inline0.dev/fr/docs/usage/directives#custom-variant), ce qui fonctionne : `@custom-variant hocus (&:hover, &:focus);`.

## Enregistrement et utilisation

Enregistrez l’instance du plugin, puis faites-y référence par le nom indiqué dans `getName()` :

```php
use TailwindPHP\tw;
use function TailwindPHP\registerPlugin;

registerPlugin(new MyCustomPlugin());

$css = tw::generate(
    '<div class="btn btn-primary card gutter-md">…</div>',
    '@plugin "my-custom-plugin"; @import "tailwindcss/utilities.css";'
);
```

Consultez [Plugins](https://tailwindphp.inline0.dev/fr/docs/plugins) pour la directive `@plugin` et [Thème](https://tailwindphp.inline0.dev/fr/docs/usage/theme) pour les valeurs exposées par `$api->theme()`.
