# `Macaw.Layers.Theme.Extension`
[🔗](https://github.com/dcoai/macaw_layers/blob/v0.3.0/lib/macaw/layers/theme/extension.ex#L1)

What an adopter registers beyond the library's vocabulary (spec/04 §3.4), so one theme
styles it: palette names in a group of the palette, and names of the color table, each
with its default, and the words its styles and defaults use, for the theme's JSON reader.

    defmodule MyApp.Marks do
      @behaviour Macaw.Layers.Theme.Extension
      def name, do: "marks"
      def styles, do: %{lane: {:furniture, %{stroke: %{type: :solid, color: {:color, :lane}}}}}
      def colors, do: %{lane: Macaw.Layers.Color.parse!("#8a8f99")}
      def words, do: %{keys: [:curve_kind], atoms: [:monotone_x]}
    end

    Macaw.Layers.Theme.new(extensions: [MyApp.Marks])

A name is a string inside a theme, an extension's as the library's (spec/04 §2.1): the
names `styles/0` and `colors/0` give, and the names in their entries' typed colors, are
read as their strings, so `:lane` and `"lane"` are one name; giving one both ways in one
map raises `ArgumentError` naming the extension.

`words/0`, optional, is the vocabulary its styles and defaults use beyond the library's:
the keys and the atom values a theme document's JSON form may spell (spec/01 §5). A theme
built in Elixir keeps every word as given; the JSON reader makes an atom of a word only
from the library's tables and the registered extensions' `words/0`
(`Macaw.Layers.Theme.Document.from_json/2`'s `extensions:`), so no atom is made from a
document.

`style_type/0`, optional, is the adopter's style type: a fragment type of a style node
(`Macaw.Layers.Fragment`, as `Macaw.Layers.Theme.Style` is) with its own hooks,
`normalize/4` and `under/3` (spec/02 §3.3), with which the theme stacks its palette
entries in place of `Macaw.Layers.Theme.Style`, in `style/2`, its list entries and its
contracts alike. At most one of a theme's extensions gives one; two raise
`ArgumentError` naming both.

A theme carries its extensions in `extensions`, given explicitly and **default closed**:
a palette or color name that neither the library nor an extension has is a fault naming
it. The names an extension adds are held to the contracts of their group, its default
entries included. Two extensions adding one name, or an extension adding a library name,
raise `ArgumentError` naming both. A color an extension adds is a color value, a literal
`%Macaw.Layers.Color{}` or a typed color; text raises `ArgumentError` naming the
extension, since a string is never a color.

# `group`

```elixir
@type group() :: :state | :furniture | :modifier
```

A group of the palette an extension's style joins.

# `colors`

```elixir
@callback colors() :: %{
  required(atom() | String.t()) =&gt; Macaw.Layers.Color.value() | map()
}
```

The names it adds to the color table, each with its default value: a color value.

# `name`

```elixir
@callback name() :: String.t()
```

The extension's name, for faults.

# `style_type`
*optional* 

```elixir
@callback style_type() :: module()
```

The style type the theme stacks its palette entries with: a fragment type of a style
node with the adopter's own hooks (spec/02 §3.3).

# `styles`

```elixir
@callback styles() :: %{required(atom() | String.t()) =&gt; {group(), map() | list()}}
```

The palette names it adds, each in a group with its default entry.

# `words`
*optional* 

```elixir
@callback words() :: %{optional(:keys) =&gt; [atom()], optional(:atoms) =&gt; [atom()]}
```

The words its styles and defaults use beyond the library's: the keys, and the atom
values, a theme document's JSON form may spell.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
