# `Macaw.Layers.Color.Form`
[🔗](https://github.com/dcoai/macaw_layers/blob/v0.3.0/lib/macaw/layers/color/form.ex#L1)

The colors' JSON adapter (spec/04 §1.6, §5): the map form of a literal color and of a
color value, for a document type that holds colors to write and read through its
`Macaw.Layers.Form` callbacks. Each is a tag, a transform's operands in their own forms,
and a theme's pinned steps `$steps`:

| Value | Map form |
|---|---|
| `%Macaw.Layers.Color{}`, 8-bit exact | `{"$rgb": "#3b6fa8"}`, eight digits when translucent |
| `%Macaw.Layers.Color{}`, any other | `{"$rgb": [r, g, b, a]}`, its fields |
| `{:color, "red"}` | `{"$color": "red"}` |
| `{:series, 3}` | `{"$series": 3}` |
| `{:ramp, "status", 0.5}` | `{"$ramp": ["status", 0.5]}` |
| `{:lighten, c, 0.3}`, and so each transform | `{"$lighten": [C, 0.3]}` |
| `{:blend, [c, …]}` | `{"$blend": [C, …]}` |
| `{:contrast, :under}`, `{:contrast, c}` | `{"$contrast": "under"}`, `{"$contrast": C}` |
| `%{500 => c, 100 => …}`, each step a literal | `{"$steps": [[100, …], [500, C]]}`, each `C` its `$rgb` |

`$rgb` reads back the canonical struct (`Macaw.Layers.Color.literal?/1`), so decoding the
payload `encode_value/1` writes of a literal color gives that color again. Its payload is
`#` and six or eight hex digits, or four numbers in their ranges; any other is no color.
A struct that is not a literal color has no form. A name is read as its string, as every
name of a theme is (spec/04 §2.1), and written from either spelling; a ramp of a name
that is none of `Macaw.Layers.Theme.ramp_names/0` is no color. A string is
never a color: an operand or a step is a color's own form, and a bare string in its place
is no color. No atom is made from a document.

A type implements `c:Macaw.Layers.Form.encode_value/1` and
`c:Macaw.Layers.Form.decode_value/2` by calling these, and lists `tags/0` among its live
tags. A value or payload these do not read is `:default`, which the kernel refuses at its
path.

The tags of visualize's `Visualize.Chart.Codec`, with `$rgb`.

# `decode_value`

```elixir
@spec decode_value(String.t(), term()) :: {:ok, term()} | :default
```

The value of one of `tags/0`, its payload already read: `{:ok, value}`, or `:default` for
a tag or payload this reader does not read.

    iex> Macaw.Layers.Color.Form.decode_value("$rgb", "#3b6fa8")
    {:ok, %Macaw.Layers.Color{r: 59.0, g: 111.0, b: 168.0, opacity: 1.0}}
    iex> Macaw.Layers.Color.Form.decode_value("$rgb", "steelblue")
    :default

# `encode_value`

```elixir
@spec encode_value(term()) :: {:ok, map()} | :default
```

A color's map form, `{:ok, form}`, or `:default` for a term that is not a color here.

    iex> Macaw.Layers.Color.Form.encode_value(Macaw.Layers.Color.parse("#3b6fa880"))
    {:ok, %{"$rgb" => "#3b6fa880"}}
    iex> Macaw.Layers.Color.Form.encode_value(Macaw.Layers.Color.rgb(59.5, 111, 168))
    {:ok, %{"$rgb" => [59.5, 111.0, 168.0, 1.0]}}

# `tags`

```elixir
@spec tags() :: [String.t(), ...]
```

The colors' tags, for a type's tag table.

---

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