Arranges child widgets in a uniform column grid, wrapping into multiple rows.
Children are laid out left-to-right, top-to-bottom. The number of columns is
set via :grid_size. Column width is floor(total_width / columns) and row
height is divided evenly across the number of rows required. Each child widget
is mounted fresh on every render pass from its {module, props} tuple.
Component tag
This module has no component_tag/0 and no Drafter.App helper. It is used by
placing it in a render tree as a {module, props} pair, or by the renderer's
{:grid, children, opts} element.
Options
:children- list of{module, props}tuples. Default[]. Each child is re-mounted from its props on every render pass, so a child holding its own state will lose it between frames:grid_size- number of columns. Default2:grid_rows-pos_integer/0or:auto. Default:auto. Carried on the state but not consulted: the row count is alwaysceil(child_count / grid_size):padding- Default1. Carried on the state but not consulted while rendering:style-map/0of style properties. Default%{}. Carried on the state but not consulted while rendering
update/2 merges the props map into the state, so every option is live.
Widget value
Drafter.get_widget_value/1 is not implemented for this widget and returns nil.
Usage
grid(children: [
{Drafter.Widget.Label, %{text: "A"}},
{Drafter.Widget.Label, %{text: "B"}},
{Drafter.Widget.Label, %{text: "C"}},
{Drafter.Widget.Label, %{text: "D"}}
], grid_size: 2)
Summary
Functions
Ignores every event and returns {:noreply, state}. The grid is not focusable and
does not forward events to its children.
Builds the grid state from props. The state is a plain map, not a struct.
Renders every child into its cell and returns one strip per row of rect.height.
Merges props into state, so every option is live-updatable.
Types
@type child_spec() :: {module(), Drafter.Widget.props()}
@type t() :: %{ children: [child_spec()], grid_size: pos_integer(), grid_rows: pos_integer() | :auto, style: map(), padding: non_neg_integer() }
Functions
@spec handle_event(Drafter.Event.t(), t()) :: {:noreply, t()}
Ignores every event and returns {:noreply, state}. The grid is not focusable and
does not forward events to its children.
@spec mount(Drafter.Widget.props()) :: t()
Builds the grid state from props. The state is a plain map, not a struct.
iex> Drafter.Widget.Grid.mount(%{})
%{children: [], grid_size: 2, grid_rows: :auto, style: %{}, padding: 1}
iex> g = Drafter.Widget.Grid.mount(%{grid_size: 3, children: [{Drafter.Widget.Label, %{}}]})
iex> {g.grid_size, length(g.children)}
{3, 1}
@spec render(t(), Drafter.Widget.rect()) :: [Drafter.Draw.Strip.t()]
Renders every child into its cell and returns one strip per row of rect.height.
Returns [] when there are no children. Each cell is div(rect.width, grid_size)
columns wide and div(rect.height, rows_needed) rows tall, where rows_needed is
ceil(child_count / grid_size); rect.height smaller than rows_needed gives a
cell height of 0 and raises ArithmeticError. A child strip's segments are
taken only up to the first one wider than the cell, so an over-wide segment ends
the row early rather than being cropped.
iex> Drafter.Widget.Grid.render(Drafter.Widget.Grid.mount(%{}), %{x: 0, y: 0, width: 10, height: 2})
[]
@spec update(Drafter.Widget.props(), t()) :: t()
Merges props into state, so every option is live-updatable.
iex> g = Drafter.Widget.Grid.mount(%{})
iex> Drafter.Widget.Grid.update(%{grid_size: 4}, g).grid_size
4