# `Ascii.Pieces.Sparkline`
[🔗](https://github.com/houllette/ascii_art/blob/main/lib/ascii/pieces/sparkline.ex#L1)

Three live block sparklines scrolling left, values at right.

Live metrics as one-row block sparklines, scrolling left as new samples
arrive, each with its label, its latest value and the span's range. As
upstream draws it, three made-up signals play; give each series its
`values` and it shows yours.

## Options

Give them to `Ascii.new/2` as `options:`, and new ones while it plays
with `Ascii.put_options/2` (or a Phoenix player's `options`) as
samples come: a series' `values` show as given, the newest at the right.
`Ascii.Telemetry.sparkline/2` gives a series a metric from your app's
telemetry, and `Ascii.BEAM.sparkline/2` this BEAM's memory, processes
and run queue.

  * `series` - up to five, each a map of:
    * `label` - its name, on the left.
    * `values` - its samples, oldest first, up to 10^15 either way; the
      newest that fit show. Without, it plays a sample signal.
    * `lo`, `hi` - the scale's ends; without, it fits what is shown.
    * `unit`, `digits` - after the latest value, and its decimals.

    Spaced a row apart when there are three or fewer. Default upstream's
    cpu, memory and requests. Upstream's `format` function is not taken:
    options are data.
  * `range` - `false` drops the min and max columns, and the lines grow
    longer. Default `true`.
  * `rate` - samples a second, 0 to 100, which labels the time axis.
    Default 4.
  * `cols` - the frame's width, 40 to 200; the lines take what the label,
    value and range leave. Default 72.
  * `rows` - the frame's height, 3 to 32, never fewer than the series and
    their header and axis need. Default 9.

A value too wide for its column, which upstream writes past it, is
written to fit: with fewer decimals, then compactly, in thousands,
millions and on (`17.5M`, `3.02G`; see `Ascii.Kit.Number`).

## Colours

In one ink, or a gradient, with `:ink` and `:gradient` (see
`Ascii.Ink`); part by part with `:parts` (see `Ascii.Parts`),
`parts: true` taking the colours suggested here:

  * `title` - the headings over the range, grey.
  * `label` - a series' name.
  * `spark` - the sparklines, blue, and `spark.1` to `spark.5`, one series
    each from the top: `spark.1` as `spark`, `spark.2` cyan, `spark.3`
    purple, `spark.4` pink, `spark.5` orange.
  * `axis` - the mark closing each line at now, grey.
  * `value`, `unit` - a series' latest value.
  * `value.min`, `value.max` - its range, grey.
  * `scale` - the time axis under them, grey.

## Keys and clicks

It takes none: it shows samples, and `Ascii.handle_event/2` ignores
every event. A Phoenix player given `interactive` and `notify` still tells
your LiveView where it was clicked, and on which part
(`Ascii.part_at/4`): `spark.2`, say, for the second series.

## Screen readers

`Ascii.describe/1` reads each series given values, its label and
latest value: "sparkline: cpu 34%, memory 2.1 gb". With no series given
values, it gives the piece's name and note.

## Example

```elixir
cpu = %{label: "cpu", unit: "%", lo: 0, hi: 100, values: [12, 30, 25, 60]}
spark = Ascii.new!("sparkline", options: %{series: [cpu], range: false, rows: 3}, parts: true)

spark = Ascii.put_options!(spark, series: [%{cpu | values: cpu.values ++ [45]}])
Ascii.describe(spark)
#=> "sparkline: cpu 45%"

{frame, _spark} = Ascii.frame(spark, 1.0)
frame.text =~ "45%"
#=> true
```

```heex
<Ascii.Phoenix.live_player id="history" piece="sparkline" options={%{series: [%{label: "cpu", unit: "%", values: @cpu}]}} parts />
```

Ported from `src/pieces/sparkline.ts` in bas3line/ascii (MIT).

---

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