# Vars

The functions behind defineVars and extendVars, with variable set types.

`Vars` holds the variable set functions, the composition helper, and their types. Applications usually call `define` and `extend` through their root aliases, [`defineVars`](/docs/api/core/defineVars) and [`extendVars`](/docs/api/core/extendVars).

```ts title="tokens.ts"
import { Vars } from 'zyzz'

const base = Vars.define({ color: { ink: '#171717' } })
const brand = Vars.extend(base, { color: { ink: '#2563eb' } })
```

## Members

[Vars.define](/docs/api/core/defineVars)

Define a typed variable set of tokens, color pairs, and conditions without
emitting CSS.

[Vars.extend](/docs/api/core/extendVars)

Override values in an existing variable set while keeping its paths and
value types.

## Vars.compose

Combine CSS text, numbers, and references into one value without resolving the references. Browsers evaluate the result, so references stay live across set scopes and extensions.

```ts
import { Vars } from 'zyzz'

const base = Vars.define(
  { color: { ink: '#171717' }, number: { opacity: 25 } },
  (vars) => ({
    color: {
      faded: Vars.compose('color', [
        'color-mix(in srgb, ',
        vars.color.ink,
        ' calc(',
        vars.number.opacity,
        ' * 1%), transparent)',
      ]),
    },
  }),
)
```

### group

* **Type:** `'color' | 'spacing'`

The value type of the complete expression, which decides where the composition can appear. A color composition can still contain numeric references, such as an opacity.

```ts
// A spacing value built from a number reference
Vars.compose('spacing', ['calc(', vars.number.space, ' * 1px)'])
```

### parts

* **Type:** `readonly (string | number | Vars.Reference)[]`

The pieces of the CSS value, joined in order. They must form a nonempty value without declaration separators, braces, or importance. The compiler reads a literal array without running application code.

```ts
Vars.compose('spacing', ['calc(', vars.number.space, ' * 2px)'])
```

### composition

* **Type:** `Vars.Composition`

An immutable value usable as a leaf, a conditional or color-scheme branch, or an override in `Vars.extend`.

```ts
// An override that keeps the composed shape
Vars.extend(base, { color: { faded: Vars.compose('color', ['transparent']) } })
```

## Types

* **`Vars.Composition`:** A composed value.
* **`Vars.Definition<values>`:** A defined set.
* **`Vars.Mappings`:** Category-to-property mappings for `defineConfig`.
* **`Vars.Overrides<values>`:** The accepted overrides for `Vars.extend`.
* **`Vars.Reference<value>`:** One reference in a set.
* **`Vars.References<values>`:** The reference tree passed to a derive callback.
* **`Vars.Values`:** The accepted value tree.

```ts title="mappings.ts"
import type { Vars } from 'zyzz'

// Shared mappings for several configs
export const mappings = {
  color: ['color', 'borderColor'],
} satisfies Vars.Mappings
```

## Errors

### Vars.InvalidError

Thrown when values cannot form a variable set, such as an incomplete color pair, a key with `!` or dots, or a derived value that replaces a path. Overrides that add a path or change a value type throw it too. The message starts with the failing path.

```ts
import { Vars } from 'zyzz'

try {
  // `section` is not a path of the base set
  Vars.extend(Vars.define({ spacing: { page: '1rem' } }), {
    spacing: { section: '2rem' },
  } as never)
} catch (error) {
  if (error instanceof Vars.InvalidError) console.error(error.message)
}
```

## React Native

Native compilation resolves references to native values. A composition compiles when its joined value is a supported native value, such as a `calc()` length or an absolute color. Others, such as `color-mix()`, fail native compilation with a diagnostic. [Values](/docs/api/react-native/values) lists the native conversions.
