
# 自定义插件

自定义插件是一个实现 `TailwindPHP\Plugin\PluginInterface` 的 PHP 类。它接收一个 `PluginAPI` 实例，并用它注册静态和函数式工具、组件及变体。使用 `registerPlugin()` 注册后，就可以在 `@plugin` 指令中按名称解析该插件——内置的排版和表单插件也使用同样的机制。

## `PluginInterface`

需要实现三个方法：

```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()` 返回在 `@plugin "..."` 中使用的标识符。
- `__invoke()` 运行插件，并通过 `$api` 注册所有内容。`$options` 数组包含来自 `@plugin` CSS 块的值。
- `getThemeExtensions()` 返回在生成工具之前要合并的主题命名空间（如果没有则返回 `[]`）。

## 示例

```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
    }
}
```

## `PluginAPI` 参考

API 与 TailwindCSS 插件的 API 相对应：

| 方法 | 签名 | 用途 |
|--------|-----------|---------|
| `addBase` | `addBase(array $css): void` | 添加基础层样式。 |
| `addUtilities` | `addUtilities(array $utilities, array $options = []): void` | 注册以选择器为键的静态工具类。 |
| `matchUtilities` | `matchUtilities(array $utilities, array $options = []): void` | 注册函数式工具；`$options['values']` 提供值映射，`$options['supportsNegativeValues']` 启用负值。 |
| `addComponents` | `addComponents(array $components, array $options = []): void` | 注册组件类（组件层）。 |
| `matchComponents` | `matchComponents(array $components, array $options = []): void` | 使用值映射注册函数式组件。 |
| `addVariant` | `addVariant(string $name, string\|array $variant): void` | 根据选择器注册静态变体。 |
| `matchVariant` | `matchVariant(string $name, callable $callback, array $options = []): void` | 注册函数式变体；`$options['values']` 提供值映射。 |
| `theme` | `theme(string $path, mixed $defaultValue = null): mixed` | 按点分隔路径读取主题值（e.g. `colors.blue.500`）。 |
| `config` | `config(?string $path = null, mixed $defaultValue = null): mixed` | 按点分隔路径读取配置值；当 `$path` 为 null 时，读取整个配置。 |
| `prefix` | `prefix(string $className): string` | 将配置的前缀应用到类名。 |

传递给 `matchUtilities`、`matchComponents` 和 `matchVariant` 的回调会接收该值，以及一个包含 `modifier` 键的第二参数数组。

选择核心 Tailwind 尚未使用的工具名称。如果插件工具与核心工具同名（例如 `tab-*`，核心 Tailwind 自 v4.3 起将其用于 `tab-size`），两者声明会落在同一规则中，而核心声明排在最后，因此会覆盖插件声明：即使插件 `tab-4` 映射到 `7`，最终仍会生成 `tab-size: 4`。

> **已知问题：** 当前版本不会应用通过 `addVariant()` 注册的变体，以及 `matchVariant()` 注册的按值变体。上方示例中的 `hocus:flex` 会编译为 `.hocus\:flex { display: flex; }`，但没有 `:hover`/`:focus` 选择器（[#10](https://github.com/inline0/tailwindphp/issues/10)）。修复此问题之前，请使用 [`@custom-variant`](https://tailwindphp.inline0.dev/zh/docs/usage/directives#custom-variant) 在 CSS 中定义变体，这种方式有效：`@custom-variant hocus (&:hover, &:focus);`。

## 注册和使用

注册插件实例，然后使用 `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";'
);
```

有关 `@plugin` 指令，请参阅[插件](https://tailwindphp.inline0.dev/zh/docs/plugins)；有关通过 `$api->theme()` 暴露的值，请参阅[主题](https://tailwindphp.inline0.dev/zh/docs/usage/theme)。
