# `Expresso.Element.Chart.Waterfall`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/element/chart/waterfall.ex#L1)

A waterfall chart: a start value, the changes to it, and the totals between
them

`Expresso.Element.Chart` sends each function of a chart of the family
`:waterfall` to this module: the check, the assigns, the layout, the marks
and the table. `docs/waterfall-charts.md` gives the design.

The chart has one series. Its first value is the start, and it draws as a
total. Each other number is a change, and it draws as a floating column
from the running total before it. The atom `:total` marks a total column,
and `{:total, value}` also gives the value that the author expects.
`columns/1` calculates the base, the end and the running total of each
column.

With `reveal true`, the check puts the columns into groups:
`members/2` gives the group of each column. Group 0 holds the start and the
totals of `totals :grow`, and the chart draws it outside the groups, so it
shows with the chart and does not dim. Each change is a group, and a total
of `totals :complete` goes into the group of the column before it. Each
group is a copy of the series with the indexes of its columns in `columns`,
and it is a child of the chart, so it takes its step from `reveal`.

A state is one set of values of the channels: one state for each group
that shows, from group 0. A total of `totals :grow` holds in each state
the running total of the changes that show, so it grows or shrinks at the
step of each change, and its value counts. A chart with frames has one
more state for each later frame, after the states of `reveal` in the first
frame. `rules/1` writes the channels of each state at its steps.

Each column has its place in the channels of
`Expresso.Element.Chart.Motion`: `--u<i>` and `--v<i>` for the corner at the
top left of column `i`, and `--w<i>` and `--h<i>` for its size. The style
attribute of the column reads the channels with the value of the first
state as the fallback, so a chart of one state needs no rule.

# `column`

```elixir
@type column() :: %{
  type: :total | :up | :down,
  change: number() | nil,
  from: number(),
  to: number(),
  total: number()
}
```

One column: its type, its change, the value at its base and at its end, and
the running total after it

# `value`

```elixir
@type value() :: number() | :total | {:total, number()}
```

A value of the series of a waterfall chart: a change, or the mark of a total

# `assigns`

```elixir
@spec assigns(Expresso.Element.Chart.t()) :: map()
```

Make the assigns of a waterfall chart that the other kinds do not have

`Expresso.Element.Chart.get_assigns/1` merges them into the assigns of a
chart with an axis.

# `cell`

```elixir
@spec cell(String.t()) :: value() | nil
```

Read a cell of a value from the CSV file of a waterfall chart

A cell holds a number, the word `total`, or the word `total` and the value
that the author expects. The function returns `nil` for another cell.

    iex> Expresso.Element.Chart.Waterfall.cell("40")
    40
    iex> Expresso.Element.Chart.Waterfall.cell("total")
    :total
    iex> Expresso.Element.Chart.Waterfall.cell(" Total 1,250 ")
    {:total, 1250}
    iex> Expresso.Element.Chart.Waterfall.cell("many")
    nil

# `check`

```elixir
@spec check(Expresso.Element.Chart.t()) ::
  {:ok, Expresso.Element.Chart.t()} | {:error, String.t()}
```

Check the options and the series of a waterfall chart

`Expresso.Element.Chart` calls this function after the check of the
categories. The chart has one series with one value for each category. The
first value is a number, and each other value is a number, `:total` or
`{:total, value}`. The sum before `{:total, value}` agrees with the value,
and each column is inside `value_range`.

# `columns`

```elixir
@spec columns([value()]) :: [column()]
```

Return the columns of the values of a waterfall chart

A total starts at zero and ends at the running total. A change starts at
the running total before it and ends at the new running total.

    iex> Expresso.Element.Chart.Waterfall.columns([50, 40, -10, :total])
    [
      %{type: :total, change: nil, from: 0, to: 50, total: 50},
      %{type: :up, change: 40, from: 50, to: 90, total: 90},
      %{type: :down, change: -10, from: 90, to: 80, total: 80},
      %{type: :total, change: nil, from: 0, to: 80, total: 80}
    ]

# `cut?`

```elixir
@spec cut?(map()) :: boolean()
```

Tell whether the axis of a waterfall chart does not hold zero

Such an axis has a break mark at its base, and each total column has a
break mark at its base.

# `inner_block`
*macro* 

# `layout`

```elixir
@spec layout(map()) :: map()
```

Add the layout of a waterfall chart to its assigns: the axis, the box of the
plot, the function `pos` from a value to a coordinate on the value axis,
and the columns of each state

A state is one set of values of the channels. A chart without steps has one
state. The axis holds zero, or it has the ends of `value_range`. The value
axis goes up the left side of a vertical chart, and along the bottom of a
horizontal chart.

# `lead`

```elixir
@spec lead(Expresso.Element.Chart.t()) :: 0 | 1
```

Return the steps that a waterfall chart takes before its first change: 1
with the groups of `reveal`, so the start and the totals show alone at the
first step, else 0

# `members`

```elixir
@spec members([value()], :grow | :complete) :: [non_neg_integer()]
```

Return the group of each column of a waterfall chart with `reveal`

The start is in group 0, and each change starts a new group. A total is in
group 0 with `totals :grow`, and in the group of the column before it with
`totals :complete`.

    iex> Expresso.Element.Chart.Waterfall.members([50, 40, 30, :total, 10, :total], :grow)
    [0, 1, 2, 0, 3, 0]
    iex> Expresso.Element.Chart.Waterfall.members([50, 40, 30, :total, 10, :total], :complete)
    [0, 1, 2, 2, 3, 3]

# `moves?`

```elixir
@spec moves?(Expresso.Element.Chart.t()) :: boolean()
```

Tell whether the columns of a waterfall chart move: with the steps of
`reveal`, or with the effect `:grow`

# `reader`

```elixir
@spec reader() :: keyword()
```

Return the options of `Expresso.Element.Chart.Csv` for the file of a
waterfall chart: the reader of a cell, and the words of its error

# `render`

```elixir
@spec render(map()) :: Phoenix.HTML.safe()
```

Draw the content of the SVG of a waterfall chart: the axis, the columns,
their labels and the connectors

# `render_slot`
*macro* 

# `rules`

```elixir
@spec rules(Expresso.Element.Chart.t()) :: [String.t()]
```

Return the CSS rules of the states of a waterfall chart with `reveal` or
with frames

The state of group `k` holds at the steps of group `k` at which group
`k + 1` and the later frames do not show, and the state of a later frame
holds at the steps of that frame. The first state is the value of each
channel in the style attribute, so it needs no rule.

# `scene`

```elixir
@spec scene(map()) :: %{
  marks: [map()],
  spans: [map()],
  channels: [{String.t(), [number()]}]
}
```

Return the places of the columns, of their labels and of the connectors in
each state, and the channels that hold them

A column has the channels `u`, `v`, `w` and `h`, its label of the total or
of the running total has `l`, its number `n`, the signed change has `m`,
and the connector at its left has `j`. A label and a connector have their
place on the value axis in the channel, and their place on the axis of the
categories in their style. `Expresso.Element.Chart.Motion` leaves out a
channel that has the same value in each state.

# `signed`

```elixir
@spec signed(number()) :: String.t()
```

Write a change with its sign

    iex> Expresso.Element.Chart.Waterfall.signed(40)
    "+40"
    iex> Expresso.Element.Chart.Waterfall.signed(-2.5)
    "-2.5"

# `table`

```elixir
@spec table(map()) :: %{headers: [String.t() | nil], rows: [[String.t()]]}
```

Return the headers and the rows of the table of a waterfall chart

The table has one row for each column, with its category, its change and
the running total after it. A total has no change.

---

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