The board mode's editor (spec/14 §22, D-152): the pure writes of a board — a cell placed, a field read from a control — and the inspector panel that makes them.
A board chart holds a %Visualize.Board{}, not a stack of uses. Every write goes
through a function here that builds the board it would make, and the mode validates
that board alone before it keeps it (Visualize.Board.validate/1), so the board the
builder holds always reads and a client can never place a cell over another or off the
grid (§22.2, §22.3). Each cell previews alone through Visualize.Board.realize/4
(preview/3, §22.6).
This module compiles only when Phoenix.Component is loaded (spec/10 §1.1, D-45, D-85).
Summary
Functions
The variables a component declares, from its flattened design, sorted (spec/14 §22.4):
the names a cell's variables may take. [] for a component the store does not hold, or
one that reaches itself.
The first place in reading order — the first row, then the first column — where a
w-by-h rectangle overlaps no cell of the board (spec/14 §22.3).
The inspector of the board mode (spec/14 §22.4): the selected cell — its title, its component, whether it joins the sync group, its variables, Edit component and Remove — then add a cell, the board's name, its window and zone, its sync group and staleness, its layout, its variables, and its faults given the store (§22.5).
The board with a cell at a rectangle, {:ok, board}, or {:error, errors}: every fault
of the board the placement would make, alone — {:off_grid, 12} for a cell that runs
past the grid, {:overlap, other} for one that shares a square, a type fault for a key
that is not an integer of the right sign (spec/14 §22.3, spec/15 §3.1). The board is the
server's: whatever rectangle a client sends, this is the one place it is written.
Each cell realized alone (spec/14 §22.6): Visualize.Board.realize/4 of a board holding
that one cell and the board's shared state, at a container width of 1200, so one cell
that cannot apply leaves every other drawn. %{cell => {:ok, svg} | {:error, lines}},
the chart a responsive root titled with the cell's title, the faults in
Visualize.Board.format_error/1's words.
Sixty rows made from a schema, for a preview where the host gave none of a feed's
(spec/14 §22.6): a :time field a second apart and ending at now, a :number window
field (window: true, D-154) its row's place, 0 to 59, as a tick counts, any other
:number field a slow sine, a :category field its order in turn — else "a", "b"
and "c" — and a :text field its own name. The rows are shaped like the feed's, not
its values.
The board mode's view of its virtual sources (spec/14 §22.9): each source's dotted
path, its state, its function's text — a draft the checker refused in place of the
stored text, with the draft's faults — its faults inline, and its preview rows, from
%{run: run, drafts: drafts}, the sources' run over the preview's data and the drafts
by path.
Functions
The variables a component declares, from its flattened design, sorted (spec/14 §22.4):
the names a cell's variables may take. [] for a component the store does not hold, or
one that reaches itself.
iex> fetch = fn {:composite, 1} -> {:ok, %{vars: %{unit: %{default: "%"}, host: %{}}}} end
iex> Visualize.Chart.Builder.Boards.declared({:composite, 1}, fetch)
[:host, :unit]
@spec free(Visualize.Board.t(), pos_integer(), pos_integer()) :: {non_neg_integer(), non_neg_integer()}
The first place in reading order — the first row, then the first column — where a
w-by-h rectangle overlaps no cell of the board (spec/14 §22.3).
iex> board = Visualize.Board.from_map!(%{cells: %{
...> a: %{x: 0, y: 0, w: 8, h: 2, ref: {:composite, 1}}
...> }})
iex> Visualize.Chart.Builder.Boards.free(board, 4, 2)
{8, 0}
iex> Visualize.Chart.Builder.Boards.free(board, 6, 1)
{0, 2}
The inspector of the board mode (spec/14 §22.4): the selected cell — its title, its component, whether it joins the sync group, its variables, Edit component and Remove — then add a cell, the board's name, its window and zone, its sync group and staleness, its layout, its variables, and its faults given the store (§22.5).
Attributes
id(:string) (required) - the panel's id.mode(:map) (required) - the board mode's assigns, as the builder derives them for the open board (spec/14 §22).target(:any) - thephx-targetof every control. Defaults tonil.
@spec place(Visualize.Board.t(), atom() | String.t(), Visualize.Board.rect()) :: {:ok, Visualize.Board.t()} | {:error, [Visualize.Board.error()]}
The board with a cell at a rectangle, {:ok, board}, or {:error, errors}: every fault
of the board the placement would make, alone — {:off_grid, 12} for a cell that runs
past the grid, {:overlap, other} for one that shares a square, a type fault for a key
that is not an integer of the right sign (spec/14 §22.3, spec/15 §3.1). The board is the
server's: whatever rectangle a client sends, this is the one place it is written.
iex> board = Visualize.Board.from_map!(%{cells: %{
...> a: %{x: 0, y: 0, w: 6, h: 2, ref: {:composite, 1}},
...> b: %{x: 6, y: 0, w: 6, h: 2, ref: {:composite, 1}}
...> }})
iex> {:ok, moved} = Visualize.Chart.Builder.Boards.place(board, :b, %{x: 6, y: 2, w: 6, h: 3})
iex> Map.take(moved.cells["b"], [:x, :y, :w, :h])
%{x: 6, y: 2, w: 6, h: 3}
iex> Visualize.Chart.Builder.Boards.place(board, :b, %{x: 4, y: 0, w: 6, h: 2})
{:error, [{[:cells, "b"], {:overlap, "a"}}]}
iex> Visualize.Chart.Builder.Boards.place(board, :b, %{x: 8, y: 4, w: 6, h: 2})
{:error, [{[:cells, "b"], {:off_grid, 12}}]}
@spec preview(Visualize.Board.t(), Visualize.Board.store(), keyword()) :: %{ required(atom()) => {:ok, String.t()} | {:error, [String.t()]} | {:fault, String.t(), [String.t()]} }
Each cell realized alone (spec/14 §22.6): Visualize.Board.realize/4 of a board holding
that one cell and the board's shared state, at a container width of 1200, so one cell
that cannot apply leaves every other drawn. %{cell => {:ok, svg} | {:error, lines}},
the chart a responsive root titled with the cell's title, the faults in
Visualize.Board.format_error/1's words.
Options
:pools- each cell's pool, by its name (default none):theme- asVisualize.Chart.apply/2takes it:describe-({cell, slot} -> {:ok, schema} | {:error, reason}), asVisualize.Board.realize/4takes it: the schema of a slot's feed:refused- each cell the binding's type check refused, by its name, with its faults (D-153): it is not realized, and is drawn as the fault panel:id- the stem of each cell's root id,<id>-<cell>(defaultvis-builder-board), so two cells drawing one design never share a root's ids or its dark-mode rule (D-188)
A cell whose binding has the wrong type — refused, or reporting a {:type_mismatch, …}
from application — is {:fault, svg, lines}: the board runtime's cell-state panel of
{:invalid, errors} and every fault's words (spec/14 §18.4, §22.6).
@spec sample(Visualize.Data.Schema.t(), DateTime.t()) :: [map()]
Sixty rows made from a schema, for a preview where the host gave none of a feed's
(spec/14 §22.6): a :time field a second apart and ending at now, a :number window
field (window: true, D-154) its row's place, 0 to 59, as a tick counts, any other
:number field a slow sine, a :category field its order in turn — else "a", "b"
and "c" — and a :text field its own name. The rows are shaped like the feed's, not
its values.
iex> schema = Visualize.Data.Schema.new!(%{t: %{type: :time}, v: %{type: :number},
...> state: %{type: :category, order: ["ok", "warn"]}})
iex> rows = Visualize.Chart.Builder.Boards.sample(schema, ~U[2026-10-11 12:00:00Z])
iex> {length(rows), List.last(rows).t, Enum.map(Enum.take(rows, 3), & &1.state)}
{60, ~U[2026-10-11 12:00:00Z], ["ok", "warn", "ok"]}
The board mode's view of its virtual sources (spec/14 §22.9): each source's dotted
path, its state, its function's text — a draft the checker refused in place of the
stored text, with the draft's faults — its faults inline, and its preview rows, from
%{run: run, drafts: drafts}, the sources' run over the preview's data and the drafts
by path.