
# 사용자 정의 플러그인

사용자 정의 플러그인은 `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-*`은 v4.3 이후 Tailwind에서 `tab-size`에 사용함), 두 선언이 같은 규칙에 들어가며 핵심 유틸리티가 나중에 적용되어 우선합니다. 따라서 `7`에 매핑된 플러그인 `tab-4`도 `tab-size: 4`을 생성합니다.

> **알려진 문제:** `addVariant()`으로 등록한 변형과 `matchVariant()`이 등록하는 값별 변형은 현재 릴리스에서 적용되지 않습니다. 위 예시의 `hocus:flex`는 `:hover`/`:focus` 선택자 없이 `.hocus\:flex { display: flex; }`로 컴파일됩니다([#10](https://github.com/inline0/tailwindphp/issues/10)). 이 문제가 해결될 때까지는 CSS에서 [`@custom-variant`](https://tailwindphp.inline0.dev/ko/docs/usage/directives#custom-variant)을 사용해 변형을 정의하세요. 이 방법은 작동합니다: `@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/ko/docs/plugins)을, `$api->theme()`를 통해 제공되는 값은 [테마](https://tailwindphp.inline0.dev/ko/docs/usage/theme)를 참조하세요.
