# `Expresso.Element.Node`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/element/node.ex#L1)

A node of a chart of flows, or a node of a tree

The `node` entity takes the name of the node as its argument, such as
`node "Losses", column: 3`.

In a chart of flows, the name is the name in the flows, and the options
change only how the chart shows the node. `Expresso.Element.Chart.Sankey`
and `Expresso.Element.Chart.Chord` read them. Only a sankey takes the
`column` option.

In a tree, the name is the identity of the node, and the default text of
its box. The node holds the nodes under it in `elements`.
`Expresso.Element.Hierarchy` reads it. The `image`, `icon`, `fields`,
`color` and `value` options add to the box, and the `layout` option sets
how the nodes under it go. `Expresso.PathTransformer` joins the path of
the image to the root of the deck, and `Expresso.IconTransformer` puts the
SVG of the icon into `svg`.

The two parents share one entity, so `Expresso.Builder` has one function
`node/2`. Each parent refuses the options of the other parent:
`chart_options/1` and `tree_options/1` return the options that a node gives.

# `t`

```elixir
@type t() :: %Expresso.Element.Node{
  __spark_metadata__: term(),
  at: term(),
  class: String.t() | nil,
  color: atom() | nil,
  column: pos_integer() | nil,
  detail: String.t() | nil,
  easing: term(),
  effect: term(),
  el: term(),
  elements: [t()] | nil,
  fields: [{String.t(), String.t()}] | nil,
  icon: String.t() | nil,
  image: String.t() | nil,
  label: String.t() | nil,
  layout: :top_down | :left_right | :stacked | nil,
  morph: term(),
  name: String.t(),
  on: term(),
  order: integer() | nil,
  parent: String.t() | nil,
  signature: term(),
  speed: term(),
  steps: term(),
  svg: String.t() | nil,
  value: number() | nil
}
```

The struct of a node

# `chart_options`

```elixir
@spec chart_options(t()) :: [atom()]
```

Return the options of a node that only a chart of flows takes and that the
node gives

    iex> Expresso.Element.Node.chart_options(%Expresso.Element.Node{name: "a", column: 2})
    [:column]

# `fields`

```elixir
@spec fields(term()) :: {:ok, [{String.t(), String.t()}]} | {:error, String.t()}
```

Make sure that a `fields` option is a list of names and texts

This function is the custom type of the option. A name is an atom or a
string, and a text is a string or a number. The function returns each name
and each text as a string, in the order of the option.

    iex> Expresso.Element.Node.fields(team: "42 people", floor: 3)
    {:ok, [{"team", "42 people"}, {"floor", "3"}]}

    iex> Expresso.Element.Node.fields([{"Cost center", "4100"}])
    {:ok, [{"Cost center", "4100"}]}

    iex> {:error, _message} = Expresso.Element.Node.fields(team: nil)

# `tree_options`

```elixir
@spec tree_options(t()) :: [atom()]
```

Return the options of a node that only a tree takes and that the node
gives, with `:on` for an `on` entity and `:node` for a nested node

    iex> Expresso.Element.Node.tree_options(%Expresso.Element.Node{name: "a", detail: "Role"})
    [:detail]

# `value`

```elixir
@spec value(term()) :: {:ok, number()} | {:error, String.t()}
```

Make sure that a `value` option is a number that is not negative

    iex> Expresso.Element.Node.value(412.5)
    {:ok, 412.5}

    iex> {:error, _message} = Expresso.Element.Node.value(-1)

---

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