
# 클래스 유틸리티

템플릿에서 `class` 속성을 만들려면 문자열을 결합하고, 조건에 따라 클래스를 전환하고, 나중에 오는 유틸리티가 앞선 유틸리티와 충돌하지 않게 해야 합니다(`p-2`과 `p-4`가 함께 남아서는 안 됩니다). JavaScript에서는 이 작업을 [clsx](https://github.com/lukeed/clsx)와 [tailwind-merge](https://github.com/dcastil/tailwind-merge)로 나눠 처리합니다. TailwindPHP에는 두 도구의 PHP 포트가 포함되어 있어, Node.js 도구 체인이나 추가 Composer 패키지 없이도 동일하게 동작합니다.

세 함수가 각기 다른 역할을 합니다. `cn()`는 구성과 충돌 해결을, `merge()`은 충돌 해결만, `join()`는 연결만 수행합니다.

## cn()

권장 유틸리티입니다. 먼저 clsx 방식으로 조건부 구성을 수행한 다음 tailwind-merge로 Tailwind 충돌을 해결하므로, 충돌하는 유틸리티 중 마지막 항목이 적용됩니다.

```php
use function TailwindPHP\cn;

// Conflicts are resolved — px-4 overrides px-2
cn('px-2 py-1', 'px-4');
// => 'py-1 px-4'

// Conditional classes via a key => bool array
cn('btn', ['btn-primary' => true, 'btn-disabled' => false]);
// => 'btn btn-primary'
```

### 허용되는 인수

`cn()`는 개수에 상관없이 인수를 받습니다. 각 인수는 clsx 의미 체계에 따라 평탄화되고 필터링됩니다:

| 인수 | 동작 |
|----------|----------|
| `string` | 그대로 추가됩니다. |
| `int` / `float` | 문자열로 변환한 뒤 추가됩니다. |
| 순차 배열 | 각 요소를 재귀적으로 처리합니다. |
| `key => bool` 배열 | 값이 참이면 각 키를 추가합니다. |
| `null`, `false`, `0`, `''` | 무시됩니다. |

```php
cn('flex', ['items-center' => true], ['p-4', ['gap-2']], null);
// => 'flex items-center p-4 gap-2'
```

### 컴포넌트 패턴

`cn()`를 사용하면 컴포넌트를 재정의할 수 있습니다. 컴포넌트 자체 클래스에 호출자가 전달한 클래스를 병합하면 충돌 시 호출자의 클래스가 우선 적용됩니다.

```php
use function TailwindPHP\cn;

function Card(array $props = []): string {
    $class = cn(
        'rounded-lg border bg-card text-card-foreground shadow-sm',
        $props['class'] ?? null
    );
    return "<div class=\"{$class}\">" . ($props['children'] ?? '') . "</div>";
}

Card(['class' => 'p-6', 'children' => 'Content']);
// <div class="rounded-lg border bg-card text-card-foreground shadow-sm p-6">Content</div>
```

선언형 다축 컴포넌트 스타일에는 `cn()`와 [variants()](https://tailwindphp.inline0.dev/ko/docs/class-utilities/variants)를 함께 사용하세요.

## merge()

충돌 해결만 수행하며 조건부 구성은 하지 않습니다. 클래스 문자열을 전달하면 같은 속성을 대상으로 하는 경우 뒤에 오는 클래스가 앞선 클래스를 덮어씁니다. 입력이 이미 일반 문자열일 때 사용하세요.

```php
use function TailwindPHP\merge;

merge('px-2 py-1 bg-red-500', 'px-4 bg-blue-500');
// => 'py-1 px-4 bg-blue-500'

// Conflict resolution is variant-aware
merge('hover:bg-red-500', 'hover:bg-blue-500');
// => 'hover:bg-blue-500'
```

`cn()`는 clsx 위에 `merge()`를 구성한 것이므로, 조건부 배열 구문이 필요하지 않을 때만 `merge()`를 직접 사용하세요.

## join()

충돌을 해결하지 않고 단순히 연결합니다. 거짓 값은 제외하지만 충돌하는 유틸리티는 모두 유지합니다. 충돌이 없음을 알고 있고 가장 비용이 적은 방법을 원할 때 사용하세요.

```php
use function TailwindPHP\join;

join('foo', 'bar', null, 'baz');
// => 'foo bar baz'
```

## 어떤 함수를 사용해야 하나요?

| 함수 | 구성(조건문, 배열) | 충돌 해결 | 사용 시점 |
|----------|:---:|:---:|----------|
| `cn()`    | 예 | 예 | 기본 선택 — 충돌할 수 있는 클래스 문자열을 만들 때 |
| `merge()` | 아니요 | 예 | 입력이 일반 문자열이고 충돌 해결만 필요할 때 |
| `join()`  | 예 | 아니요 | 충돌이 없고 최소한의 처리를 원할 때 |

## 가져오기

```php
use function TailwindPHP\cn;
use function TailwindPHP\merge;
use function TailwindPHP\join;
```

세 함수 모두 기본 `TailwindPHP` 네임스페이스에 있으며 패키지에 포함됩니다. clsx(Luke Edwards 제작)와 tailwind-merge(Dany Castillo 제작)의 PHP 포트입니다.
