The builder for the declarative layer (spec/14 §16, D-78).
Every function here returns a fragment — a design map carrying the keys that one
function sets and no others — and the pipe is Visualize.Chart.compose/2: a design is
the fold of its fragments, which is Visualize.Chart.compose/1 over the list. Nothing
validates, defaults or realises anything, so the fold is a fragment too and becomes a
chart through Visualize.Chart.from_map/1 or an applied chart through
Visualize.Chart.apply/2, which is where it must validate.
What the builder adds over the literal map is the schema. Each function sets its node's
required keys from its positional arguments and takes the node's remaining keys as
opts, checked against Visualize.Chart.Schema.describe/1: an option that is not a key
of that node kind raises ArgumentError at the call rather than reaching the validator
as a path in a design fifty lines long. A mark's channels and options are checked the
same way against Visualize.Chart.Schema.channels/1 and Visualize.Chart.Schema.options/1
of its type.
The mark, transform and scale functions are not written here: they are generated from
the schema at compile time (spec/14 §16.6, D-79), one documented function per mark type
(line/3, rect/3, …), per transform op (bin/3, stack/3, treemap/2, …) and per
scale kind (linear_scale/2, time_scale/2, band_scale/2, … — every kind takes the
suffix because band is a mark type as well). A type added to the schema grows the
builder with no edit to it; mark/4 and scale/3 remain for a type that is a value.
var/2 declares a variable and its default under the design's vars;
Visualize.Chart.var/1 builds the %Visualize.Chart.Var{} term that uses one. They
are different modules and different arities, so a caller may import both.
Examples
iex> import Visualize.Chart.Build
iex> {:ok, design} =
...> Visualize.Chart.compose([
...> chart(meta: %{name: "Uptime"}),
...> source(:primary, [:t, :v]),
...> cartesian(),
...> time_scale(:x),
...> linear_scale(:y, domain: [0, :auto]),
...> axis(:x, :bottom, ticks: 4),
...> line(:primary, %{x: :t, y: :v}),
...> title(["Uptime"])
...> ])
iex> design.marks
[%{type: :line, data: :primary, channels: %{x: :t, y: :v}}]
iex> design.frames.main.scales
%{x: %{kind: :time}, y: %{kind: :linear, domain: [0, :auto]}}
iex> {:ok, _chart} = Visualize.Chart.from_map(design)
Summary
Types
A design map carrying the keys one builder function sets (spec/14 §16.1).
A node's remaining keys, as a keyword list or a map.
Functions
As adopt/3 reading the same name in the other frame (spec/14 §4.3).
A scale adopted from another frame (spec/14 §4.3, #384): this frame reads frame's
scale under name, so the node is said once and the domain is shared, while the
range stays this frame's own.
A :arc mark, as mark/4 of that type (spec/14 §5.2).
A :area mark, as mark/4 of that type (spec/14 §5.2).
As axis/3 with no options.
One axis of the frame, drawing scale on side (spec/14 §4.4).
A :band mark, as mark/4 of that type (spec/14 §5.2).
A :band scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :bin step appended to a data node (spec/14 §5.4).
As cartesian/2 under the name :main, with no options.
A :cartesian frame (spec/14 §4.1).
A named :cartesian frame (spec/14 §4.1): a design holds its frames by name, and a
design that declares one names it :main unless it says otherwise.
The seed a design is folded onto: the current schema version (spec/14 §9).
A :chord step appended to a data node (spec/14 §5.4).
A :circle mark, as mark/4 of that type (spec/14 §5.2).
A :cluster step appended to a data node (spec/14 §5.4).
A :contour step appended to a data node (spec/14 §5.4).
A :delaunay step appended to a data node (spec/14 §5.4).
A :density step appended to a data node (spec/14 §5.4).
A :diverging scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :facet frame (spec/14 §4.6).
A named :facet frame (spec/14 §4.6).
A :filter step appended to a data node (spec/14 §5.4).
A :fold step appended to a data node (spec/14 §5.4).
A :force step appended to a data node (spec/14 §5.4).
The :data node of a mark reading source (spec/14 §5.4) — a node, not a fragment.
A :geo frame (spec/14 §4.6).
A named :geo frame (spec/14 §4.1).
As gradient/3 with no options.
One named paint under defs (spec/14 §2.7): a gradient of the kind, opts its remaining
keys. stops: takes %{offset, colour, opacity} maps, or {offset, colour} and
{offset, colour, opacity} tuples, which read as the maps.
A :hexbin step appended to a data node (spec/14 §5.4).
The fragments, each in the frame name (spec/14 §16.3, #383).
How the chart behaves beside others on a page (spec/14 §2.9, #466): sync: names the
group whose charts share hover, frame: the frame whose x it reads.
As label/3 with no options.
One label of the frame: a text at an anchor (spec/14 §6.1).
The grid the design's frames are placed on (spec/14 §2.8, #384): columns and rows
as weights, gap in pixels between cells. A frame takes its place with cell:.
As legend/2 with no options.
The frame's legend, explaining scale (spec/14 §4.5).
A :line mark, as mark/4 of that type (spec/14 §5.2).
A :linear scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :log scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :lttb step appended to a data node (spec/14 §5.4).
A :m4 step appended to a data node (spec/14 §5.4).
As mark/4 with no options.
One mark of the design (spec/14 §5.1): a type, its data, its channels.
A :needle mark, as mark/4 of that type (spec/14 §5.2).
A :ordinal scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :pack step appended to a data node (spec/14 §5.4).
The value a :colour key takes to refer to a gradient of defs (spec/14 §3.2).
A :partition step appended to a data node (spec/14 §5.4).
A :path mark, as mark/4 of that type (spec/14 §5.2).
A :percentile_band mark, as mark/4 of that type (spec/14 §5.2).
A :polar frame (spec/14 §4.6): angle and r are its scales.
A named :polar frame (spec/14 §4.1).
A :power scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :projection step appended to a data node (spec/14 §5.4).
A :quantile scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :quantize scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :radial scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :rect mark, as mark/4 of that type (spec/14 §5.2).
A :rose mark, as mark/4 of that type (spec/14 §5.2).
A :rule mark, as mark/4 of that type (spec/14 §5.2).
A :sankey step appended to a data node (spec/14 §5.4).
As scale/3 with no options.
One declared scale of the frame (spec/14 §4.3); opts are its remaining keys.
A :sequential scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :sort step appended to a data node (spec/14 §5.4).
As source/3 with no options.
One typed slot under sources (spec/14 §2.3): the fields the design reads from it.
A :spectrum step appended to a data node (spec/14 §5.4).
A :sqrt scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :stack step appended to a data node (spec/14 §5.4).
As style/3 with no further keys.
One named style under styles (spec/14 §3.1).
A :sum step appended to a data node (spec/14 §5.4).
A :symbol mark, as mark/4 of that type (spec/14 §5.2).
A :symlog scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :take step appended to a data node (spec/14 §5.4).
A :text mark, as mark/4 of that type (spec/14 §5.2).
The design's theme: a name, or an inline :theme node (spec/14 §2.5).
A :threshold scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :tiles mark, as mark/4 of that type (spec/14 §5.2).
A :time scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
As title/2 with no options.
The design's title: label/3 at the :title anchor (spec/14 §6.3).
A :tree step appended to a data node (spec/14 §5.4).
A :treemap step appended to a data node (spec/14 §5.4).
As var/3 with no options.
The declaration of a variable and its default under vars (spec/14 §2.4).
A :voronoi step appended to a data node (spec/14 §5.4).
A :window step appended to a data node (spec/14 §5.4).
A :x_band mark, as mark/4 of that type (spec/14 §5.2).
Types
A mark's data: a source name, or the :data node from/1 starts (spec/14 §5.4).
A design map carrying the keys one builder function sets (spec/14 §16.1).
A node's remaining keys, as a keyword list or a map.
Functions
As adopt/3 reading the same name in the other frame (spec/14 §4.3).
A scale adopted from another frame (spec/14 §4.3, #384): this frame reads frame's
scale under name, so the node is said once and the domain is shared, while the
range stays this frame's own.
iex> import Visualize.Chart.Build
iex> in_frame(:day, [adopt(:y, :year)])
[%{frames: %{day: %{scales: %{y: {:frame, :year, :y}}}}}]
@spec arc(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :arc mark, as mark/4 of that type (spec/14 §5.2).
Required channels: value. Optional channels: start, end, inner, outer, series. Options: inner_radius, outer_radius, corner_radius, pad_angle, start_angle, end_angle.
@spec area(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :area mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, y. Optional channels: x0, x1, y0, y1, series. Options: closed.
As axis/3 with no options.
One axis of the frame, drawing scale on side (spec/14 §4.4).
@spec band(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :band mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x0, x1. Optional channels: y, series. Options: height.
A :band scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :bin step appended to a data node (spec/14 §5.4).
bin(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: thresholds, as.
@spec cartesian() :: fragment()
As cartesian/2 under the name :main, with no options.
A :cartesian frame (spec/14 §4.1).
opts are the frame's keys; its scales, axes and legend are their own fragments
(scale/3, axis/3, legend/2). A frame carries no size — the render gives it (§4.2).
A named :cartesian frame (spec/14 §4.1): a design holds its frames by name, and a
design that declares one names it :main unless it says otherwise.
@spec chart() :: fragment()
As chart/1 with no options.
The seed a design is folded onto: the current schema version (spec/14 §9).
opts are the remaining keys of the :design node (spec/14 §2.1).
A :chord step appended to a data node (spec/14 §5.4).
chord(data, fields, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: size, padding, output, nodes, id.
@spec circle(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :circle mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, y. Optional channels: value, series. Options: radius.
A :cluster step appended to a data node (spec/14 §5.4).
cluster(data, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: id, by, field, size, output, orientation, link.
A :contour step appended to a data node (spec/14 §5.4).
contour(data, field, size, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: thresholds.
A :delaunay step appended to a data node (spec/14 §5.4).
delaunay(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: output.
A :density step appended to a data node (spec/14 §5.4).
density(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: field, size, bandwidth, thresholds.
A :diverging scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
@spec facet() :: fragment()
As facet/1 with no options.
A :facet frame (spec/14 §4.6).
by: and columns:, the keys of the :facet node, are lifted into the frame's facet
key: a :facet frame and its facet node name the same thing.
A named :facet frame (spec/14 §4.6).
A :filter step appended to a data node (spec/14 §5.4).
filter(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: test, value.
A :fold step appended to a data node (spec/14 §5.4).
fold(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: as.
A :force step appended to a data node (spec/14 §5.4).
force(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: field, size, output, nodes, id, strength, distance, alpha, ticks.
The :data node of a mark reading source (spec/14 §5.4) — a node, not a fragment.
It carries no transforms key, so a mark that reads its source directly and one built
by from/1 alone are the same map; the generated appenders — one per transform op (spec/14 §16.6) — add the steps.
@spec geo() :: fragment()
As geo/1 with no options.
A :geo frame (spec/14 §4.6).
The projection is the frame's projection: key, a :projection node.
A named :geo frame (spec/14 §4.1).
As gradient/3 with no options.
One named paint under defs (spec/14 §2.7): a gradient of the kind, opts its remaining
keys. stops: takes %{offset, colour, opacity} maps, or {offset, colour} and
{offset, colour, opacity} tuples, which read as the maps.
iex> Visualize.Chart.Build.gradient(:area, :linear, stops: [{0, :series_1, 0.8}, {1, :series_1, 0.1}])
%{defs: %{area: %{kind: :linear, stops: [%{offset: 0, colour: :series_1, opacity: 0.8}, %{offset: 1, colour: :series_1, opacity: 0.1}]}}}
A :hexbin step appended to a data node (spec/14 §5.4).
hexbin(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: radius, size, output.
The fragments, each in the frame name (spec/14 §16.3, #383).
The frame functions take a name — cartesian/2, polar/2 — but scale/3, axis/3,
legend/2 and the generated scale functions declare the design's one frame, and a named
twin of each would double the builder's surface for no new meaning. This says it once:
each fragment's frame is renamed to name, and every mark and every label it carries is
given frame: name unless it already says one (spec/14 §5.1, §6.1). A list in and a list
out, so it stands in a fold where its fragments would.
iex> import Visualize.Chart.Build
iex> in_frame(:now, [polar(), linear_scale(:r, domain: [0, 4]), line(:load, %{x: :t, y: :v})])
[
%{frames: %{now: %{kind: :polar}}},
%{frames: %{now: %{scales: %{r: %{kind: :linear, domain: [0, 4]}}}}},
%{marks: [%{type: :line, data: :load, channels: %{x: :t, y: :v}, frame: :now}]}
]A fragment carrying more than one frame raises ArgumentError: this function says which
frame a thing belongs to, and a fragment already holding two has nothing to be told.
How the chart behaves beside others on a page (spec/14 §2.9, #466): sync: names the
group whose charts share hover, frame: the frame whose x it reads.
iex> Visualize.Chart.Build.interaction(sync: "dash-42")
%{interaction: %{sync: "dash-42"}}
As label/3 with no options.
One label of the frame: a text at an anchor (spec/14 §6.1).
The grid the design's frames are placed on (spec/14 §2.8, #384): columns and rows
as weights, gap in pixels between cells. A frame takes its place with cell:.
iex> Visualize.Chart.Build.layout(columns: [4, 3, 2, 1], gap: 8)
%{layout: %{columns: [4, 3, 2, 1], gap: 8}}
As legend/2 with no options.
The frame's legend, explaining scale (spec/14 §4.5).
@spec line(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :line mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, y. Optional channels: series. Options: closed.
A :linear scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :log scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :lttb step appended to a data node (spec/14 §5.4).
lttb(data, fields, n, opts), with data a node from/1 started or a source name, read as from/1
of it.
A :m4 step appended to a data node (spec/14 §5.4).
m4(data, fields, width, opts), with data a node from/1 started or a source name, read as from/1
of it.
@spec mark(atom(), data(), opts() | Visualize.Chart.Var.t()) :: fragment()
As mark/4 with no options.
One mark of the design (spec/14 §5.1): a type, its data, its channels.
data is a source name or the :data node from/1 starts. A key of channels that is
not a channel of the type, and a key of an options: option that is not an option of the
type, raise ArgumentError (spec/14 §5.2, §5.3); a %Visualize.Chart.Var{} standing for
the whole node passes through unchecked. Which required channels a node must carry is the
validator's word, not the builder's (D-69, D-78).
@spec needle(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :needle mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x. Optional channels: y, series. Options: inner_radius, width, tail, hub, cap.
A :ordinal scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :pack step appended to a data node (spec/14 §5.4).
pack(data, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: id, by, field, size, output, padding.
The value a :colour key takes to refer to a gradient of defs (spec/14 §3.2).
iex> Visualize.Chart.Build.paint(:area)
{:paint, :area}
A :partition step appended to a data node (spec/14 §5.4).
partition(data, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: id, by, field, size, output, padding.
@spec path(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :path mark, as mark/4 of that type (spec/14 §5.2).
Required channels: path. Optional channels: series.
@spec percentile_band(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :percentile_band mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, median. Optional channels: inner_lo, inner_hi, outer_lo, outer_hi.
@spec polar() :: fragment()
As polar/1 with no options.
A :polar frame (spec/14 §4.6): angle and r are its scales.
A named :polar frame (spec/14 §4.1).
A :power scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :projection step appended to a data node (spec/14 §5.4).
projection(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: field.
A :quantile scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :quantize scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :radial scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
@spec rect(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :rect mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x0, x1, y0, y1. Optional channels: value, series. Options: corner_radius.
@spec rose(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :rose mark, as mark/4 of that type (spec/14 §5.2).
Required channels: angle. Optional channels: value, series. Options: width, inner_radius, outer_radius, pad_angle.
@spec rule(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :rule mark, as mark/4 of that type (spec/14 §5.2).
Optional channels: x, y, series.
A :sankey step appended to a data node (spec/14 §5.4).
sankey(data, fields, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: size, padding, output, nodes, id.
As scale/3 with no options.
One declared scale of the frame (spec/14 §4.3); opts are its remaining keys.
A :sequential scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :sort step appended to a data node (spec/14 §5.4).
sort(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: order.
As source/3 with no options.
One typed slot under sources (spec/14 §2.3): the fields the design reads from it.
opts are the slot's remaining keys, default: among them.
A :spectrum step appended to a data node (spec/14 §5.4).
spectrum(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: time, every, samples, window, detrend, as.
A :sqrt scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :stack step appended to a data node (spec/14 §5.4).
stack(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: order, offset.
As style/3 with no further keys.
One named style under styles (spec/14 §3.1).
keys and opts are both style keys, opts merged over keys; every one is checked.
A :sum step appended to a data node (spec/14 §5.4).
sum(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: by, as.
@spec symbol(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :symbol mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, y. Optional channels: value, series.
A :symlog scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
A :take step appended to a data node (spec/14 §5.4).
take(data, n, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: side.
@spec text(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :text mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x, y. Optional channels: value, series.
The design's theme: a name, or an inline :theme node (spec/14 §2.5).
A :threshold scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
@spec tiles(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :tiles mark, as mark/4 of that type (spec/14 §5.2).
A :time scale declared under the frame, as scale/3 of that kind (spec/14 §4.3).
As title/2 with no options.
The design's title: label/3 at the :title anchor (spec/14 §6.3).
A :tree step appended to a data node (spec/14 §5.4).
tree(data, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: id, by, field, size, output, orientation, link.
A :treemap step appended to a data node (spec/14 §5.4).
treemap(data, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: id, by, field, size, output, padding, tile.
As var/3 with no options.
The declaration of a variable and its default under vars (spec/14 §2.4).
Visualize.Chart.var/1 builds the term that uses one; this declares it.
A :voronoi step appended to a data node (spec/14 §5.4).
voronoi(data, fields, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: size, output.
A :window step appended to a data node (spec/14 §5.4).
window(data, field, opts), with data a node from/1 started or a source name, read as from/1
of it. Its remaining keys: from, to.
@spec x_band(data(), opts() | Visualize.Chart.Var.t(), opts()) :: fragment()
A :x_band mark, as mark/4 of that type (spec/14 §5.2).
Required channels: x0, x1. Optional channels: series.