Renders a coloured placeholder block useful during development and layout design.
Each placeholder is assigned a distinct pastel background colour derived from a number embedded in its text label. Text is centered vertically and horizontally inside the block, and an optional border can be drawn around the content area.
Component tag
Tag :placeholder, built by Drafter.App as {:placeholder, opts}:
placeholder(opts)placeholder/1 takes a keyword list only — there is no positional argument, so
the label must be given as text: (or label:, which the element accepts as
an alias).
Options
:text-String.t/0label drawn in the middle row. Default"Placeholder". The first run of digits in the text picks the pastel colour:"Placeholder 3"takes the third entry, text with no digits takes the first.:label-String.t/0alias for:text, read only byfrom_component_opts/2and taking precedence over:text. Default: the value of:text.:padding-non_neg_integer/0padding applied on all four sides when computing the content area. Default2. Nothing is drawn once2 * paddingreaches the rect width or height.:align-:left | :center | :right. Default:center. Stored on the state and returned bymount/1, butrender/2always centres the text.:border-boolean/0, draw a box border around the content area. Defaultfalse.:style-map/0of style attributes applied to every segment. Default throughmount/1is the auto-generated%{fg: ..., bg: ...}pastel pair; default through the component tag is%{}, which discards the pastel colour.
Only :text is live-updatable through the component tree:
update_props_from_mount/3 returns :text alone. update/2 called directly
merges any key.
Usage
placeholder(text: "Placeholder 1")
placeholder(text: "Placeholder 2", border: true, padding: 4)
Summary
Functions
The component tag this widget registers under.
Builds the props map for a {:placeholder, opts} element.
Ignores every event and returns {:noreply, state}. The widget is not focusable
and never consumes input.
Builds the widget state from props.
The number of rows the element asks for: opts[:height], default 3.
Draws the block into rect.
Merges props into state and returns the result.
Narrows a re-render to :text, the only prop that reaches an already-mounted
placeholder through the component tree.
Types
@type t() :: %{ text: String.t(), style: map(), padding: non_neg_integer(), align: :left | :center | :right, border: boolean() }
Functions
@spec component_tag() :: :placeholder
The component tag this widget registers under.
iex> Drafter.Widget.Placeholder.component_tag()
:placeholder
Builds the props map for a {:placeholder, opts} element.
The positional argument is ignored. Reads :label first and falls back to
:text, both defaulting to "Placeholder"; then :padding (default 2),
:align (default :center), :border (default false) and :style
(default %{}). Because :style is always present in the result, a placeholder
built from the component tag never picks up the pastel colour mount/1 would
otherwise generate.
iex> Drafter.Widget.Placeholder.from_component_opts(nil, [])
%{align: :center, border: false, padding: 2, style: %{}, text: "Placeholder"}
iex> Drafter.Widget.Placeholder.from_component_opts(nil, label: "Left", text: "Right")
%{align: :center, border: false, padding: 2, style: %{}, text: "Left"}
@spec handle_event(Drafter.Event.t(), t()) :: {:noreply, t()}
Ignores every event and returns {:noreply, state}. The widget is not focusable
and never consumes input.
@spec mount(Drafter.Widget.props()) :: t()
Builds the widget state from props.
Reads :text (default "Placeholder"), :style (default: a pastel
%{fg: rgb, bg: rgb} pair chosen from the digits in the text), :padding
(default 2), :align (default :center) and :border (default false).
iex> Drafter.Widget.Placeholder.mount(%{text: "Placeholder 1"})
%{align: :center, border: false, padding: 2, style: %{bg: {77, 17, 68}, fg: {230, 230, 230}}, text: "Placeholder 1"}
iex> Drafter.Widget.Placeholder.mount(%{text: "x", style: %{}, padding: 0, border: true})
%{align: :center, border: true, padding: 0, style: %{}, text: "x"}
@spec preferred_height( term(), keyword() ) :: pos_integer()
The number of rows the element asks for: opts[:height], default 3.
iex> Drafter.Widget.Placeholder.preferred_height(nil, [])
3
iex> Drafter.Widget.Placeholder.preferred_height(nil, height: 12)
12
@spec render(t(), Drafter.Widget.rect()) :: [Drafter.Draw.Strip.t()]
Draws the block into rect.
Returns [] when 2 * padding leaves no content width or height. Without a
border the result has one strip per content row, with the text centred on the
middle row. With a border the result has content_height + 2 strips: a top rule,
the bordered rows, and a bottom rule.
@spec update(Drafter.Widget.props(), t()) :: t()
Merges props into state and returns the result.
Every key in props replaces the one on the state, including :style, so the
pastel colour chosen at mount is only kept while :style stays absent.
iex> state = Drafter.Widget.Placeholder.mount(%{text: "x", style: %{}})
iex> Drafter.Widget.Placeholder.update(%{text: "y", border: true}, state)
%{align: :center, border: true, padding: 2, style: %{}, text: "y"}
Narrows a re-render to :text, the only prop that reaches an already-mounted
placeholder through the component tree.
iex> props = Drafter.Widget.Placeholder.from_component_opts(nil, text: "New", border: true)
iex> Drafter.Widget.Placeholder.update_props_from_mount(props, %{}, [])
%{text: "New"}