
# Varianter

`variants()` er en PHP-port af [CVA (Class Variance Authority)](https://github.com/joe-bell/cva). Den omdanner en deklarativ konfiguration — en grundstil, navngivne variantakser og standardværdier — til en funktion, der knytter egenskaber til en klassestreng. Brug den, når en komponent har stilvalg som størrelse og formål, der skal kombineres.

```php
use function TailwindPHP\variants;

$button = variants([
    'base' => 'btn font-semibold border rounded',
    'variants' => [
        'intent' => [
            'primary'   => 'bg-blue-500 text-white',
            'secondary' => 'bg-gray-200 text-gray-800',
        ],
        'size' => [
            'sm' => 'text-sm px-2 py-1',
            'md' => 'text-base px-4 py-2',
        ],
    ],
    'defaultVariants' => [
        'intent' => 'primary',
        'size'   => 'md',
    ],
]);

$button();
// => 'btn font-semibold border rounded bg-blue-500 text-white text-base px-4 py-2'
```

`variants()` returnerer en `callable`; kald den med et egenskabsarray (eller uden argumenter) for at få den løste streng.

## Konfiguration

| Nøgle | Type | Formål |
|-----|------|---------|
| `base` | `string` | Klasser, der anvendes på hvert output. |
| `variants` | `array` | Navngivne akser, som hver knytter værdinavne til klassestrenge. |
| `compoundVariants` | `array` | Klassestrenge, der kun anvendes, når flere variantværdier kombineres. |
| `defaultVariants` | `array` | Værdi pr. akse, der bruges, når en egenskab udelades. |

Alle nøgler er valgfrie. Uden `variants` returneres `base` samt eventuelle brugerdefinerede klasser:

```php
$x = variants(['base' => 'box']);
$x();                          // => 'box'
$x(['class' => 'p-4']);        // => 'box p-4'
```

En variantværdi kan knyttes til `null`, så den ikke bidrager med noget — nyttigt som en eksplicit "unset"-indstilling for en akse.

## Kald af resultatet

Angiv et enkelt egenskabsarray som i CVA. Nøglerne svarer til dine variantaksers navne; udeladte akser bruger `defaultVariants` som reserveværdi.

```php
$button(['intent' => 'secondary']);
// => 'btn font-semibold border rounded bg-gray-200 text-gray-800 text-base px-4 py-2'

$button(['size' => 'sm', 'class' => 'mt-4']);
// => 'btn font-semibold border rounded bg-blue-500 text-white text-sm px-2 py-1 mt-4'
```

Nøglen `class` (og dens alias `className`) føjes til slutningen af outputtet. Tilføjelsen alene løser ikke konflikter — se komponentmønstret nedenfor.

## compoundVariants

Hver post i `compoundVariants` er et array med variantbetingelser samt en `class` (eller `className`) med ekstra klasser. Klasserne anvendes kun, når alle betingelser passer til de løste egenskaber (inklusive standardværdierne). En betingelsesværdi kan være en enkelt streng eller et array af strenge, der matcher en af flere værdier.

```php
$button = variants([
    'base' => 'btn',
    'variants' => [
        'intent' => [
            'primary' => 'bg-blue-500',
            'warning' => 'bg-yellow-500',
            'danger'  => 'bg-red-500',
        ],
        'size' => ['sm' => 'text-sm', 'md' => 'text-base'],
    ],
    'compoundVariants' => [
        // Applies only when intent=primary AND size=md
        ['intent' => 'primary', 'size' => 'md', 'class' => 'uppercase'],
        // Applies when intent is warning OR danger
        ['intent' => ['warning', 'danger'], 'class' => '!border-red-500'],
    ],
    'defaultVariants' => ['intent' => 'primary', 'size' => 'md'],
]);

$button();
// => 'btn bg-blue-500 text-base uppercase'

$button(['intent' => 'danger']);
// => 'btn bg-red-500 text-base !border-red-500'
```

## Komponentmønster

`variants()` føjer kun `class` til; hvis kaldende kode skal kunne tilsidesætte variantstandarderne, skal outputtet indpakkes i [cn()](https://tailwindphp.inline0.dev/da/docs/class-utilities), så konflikter løses til fordel for den kaldende kode.

```php
use function TailwindPHP\variants;
use function TailwindPHP\cn;

function Button(array $props = []): string {
    static $styles = null;
    $styles ??= variants([
        'base' => 'inline-flex items-center justify-center rounded-md font-medium',
        'variants' => [
            'variant' => [
                'default' => 'bg-primary text-primary-foreground hover:bg-primary/90',
                'outline' => 'border border-input bg-background hover:bg-accent',
                'ghost'   => 'hover:bg-accent hover:text-accent-foreground',
            ],
            'size' => [
                'default' => 'h-10 px-4 py-2',
                'sm'      => 'h-9 px-3',
                'lg'      => 'h-11 px-8',
            ],
        ],
        'defaultVariants' => ['variant' => 'default', 'size' => 'default'],
    ]);

    // cn() merges variant output with custom classes, resolving conflicts
    $class = cn($styles($props), $props['class'] ?? null);
    $text  = $props['children'] ?? 'Button';
    return "<button class=\"{$class}\">{$text}</button>";
}

// The custom px-8 wins over the variant's px-3 via cn()
Button(['variant' => 'outline', 'size' => 'sm', 'class' => 'mt-4 px-8']);
```

Cachen `static $styles` opbygger variantkonfigurationen én gang og genbruger den på tværs af kald.

## compose()

`compose()` fletter flere variantkomponenter til én. Den sammensatte funktion sender hver egenskab videre til alle komponenter, samler deres output og tilføjer eventuelle `class`/`className`.

```php
use function TailwindPHP\variants;
use function TailwindPHP\compose;

$box   = variants(['variants' => ['shadow' => ['sm' => 'shadow-sm', 'md' => 'shadow-md']]]);
$stack = variants(['variants' => ['gap' => ['1' => 'gap-1', '2' => 'gap-2']]]);
$card  = compose($box, $stack);

$card(['shadow' => 'md', 'gap' => '2']);
// => 'shadow-md gap-2'
```

Dermed kan genanvendelige akser (afstand, højde, layout) holdes i separate definitioner og kombineres pr. komponent.

## Importer

```php
use function TailwindPHP\variants;
use function TailwindPHP\compose;
```

Begge findes i hovednavnerummet `TailwindPHP` og følger med pakken — en PHP-port af CVA af Joe Bell.
