An inline hyperlink widget that opens a URL in the system browser when activated.
Renders as underlined text. When focused or hovered the text is wrapped in square
brackets ([label]) for visibility. Activating via Enter or mouse click invokes the
platform's default browser opener (open on macOS, xdg-open on Linux,
cmd /c start on Windows).
Component tag
Tag :link, built by Drafter.App as {:link, text, opts}:
link(text, opts)
link(text, url)The positional argument becomes :text, falling back to opts[:text] when
nil. Passing a binary second argument is shorthand for [url: binary].
Options
:text-String.t/0display text. Defaultnil, in which case the:urlis used as the label. Supplied positionally through thelink/2element, falling back toopts[:text]when the positional value isnil:url-String.t/0to open. Defaultnil; without it, activating the link does nothing:tooltip- stored on the widget state; never rendered. Defaultnil:style-map/0of style overrides. Default%{}:class- theme class atom or list of them, reachingmount/1as:classes. Default[]:app_module- module supplying a per-app theme, passed by the renderer as:__app_module__. Defaultnil
mount/1 always starts :focused and :hovered at false and ignores props of
those names. update/2 re-reads every option, but through the component tree only
:text, :url and :app_module are re-applied on a re-render, making :style,
:classes and :tooltip effectively mount-only there.
Widget value
Drafter.get_widget_value/1 returns the link's :text, which is nil when the
label falls back to the URL.
Usage
link("Elixir website", url: "https://elixir-lang.org")
Summary
Functions
The registry tag for this widget.
Turns the {:link, text, opts} element into a props map for mount/1.
Handles events directly instead of going through Drafter.Widget.EventRouter.
Builds the link state from props.
Always 1: the link occupies a single row.
Draws the link as a single underlined strip.
Callback implementation for Drafter.Widget.unmount/1.
Folds fresh props into state, re-reading :text, :url, :style, :classes,
:app_module and :tooltip. :focused and :hovered are left alone.
Narrows the props a re-render feeds to update/2 to :text, :url and
:app_module, so :style, :classes and :tooltip stay as mounted.
Types
Functions
@spec component_tag() :: :link
The registry tag for this widget.
iex> Drafter.Widget.Link.component_tag()
:link
@spec from_component_opts( term(), keyword() ) :: Drafter.Widget.props()
Turns the {:link, text, opts} element into a props map for mount/1.
A nil positional text falls back to opts[:text]. :class is normalised into
:classes and :__app_module__ becomes :app_module.
iex> Drafter.Widget.Link.from_component_opts("Elixir", url: "https://elixir-lang.org")
%{text: "Elixir", url: "https://elixir-lang.org", style: %{}, classes: [], tooltip: nil, app_module: nil}
@spec handle_event(Drafter.Event.t() | atom(), t() | Drafter.Widget.props()) :: {:ok, t()} | {:noreply, t()}
Handles events directly instead of going through Drafter.Widget.EventRouter.
{:key, :enter} and a mouse release run the platform browser opener for :url
and return {:ok, state} unchanged; with no :url nothing is run. {:focus}
sets both :focused and :hovered, {:blur} clears both, and
:hover/:unhover move :hovered alone. Everything else, including Space,
returns {:noreply, state}.
iex> l = Drafter.Widget.Link.mount(%{text: "Elixir", url: "https://elixir-lang.org"})
iex> {:ok, focused} = Drafter.Widget.Link.handle_event({:focus}, l)
iex> {focused.focused, focused.hovered}
{true, true}
iex> l = Drafter.Widget.Link.mount(%{text: "Elixir"})
iex> Drafter.Widget.Link.handle_event({:key, :" "}, l) |> elem(0)
:noreply
@spec mount(Drafter.Widget.props()) :: t()
Builds the link state from props.
iex> l = Drafter.Widget.Link.mount(%{text: "Elixir", url: "https://elixir-lang.org"})
iex> {l.text, l.url, l.focused, l.hovered}
{"Elixir", "https://elixir-lang.org", false, false}
iex> l = Drafter.Widget.Link.mount(%{})
iex> {l.text, l.url, l.style, l.classes, l.tooltip}
{nil, nil, %{}, [], nil}
@spec preferred_height( term(), keyword() ) :: pos_integer()
Always 1: the link occupies a single row.
@spec render(t() | Drafter.Widget.props(), Drafter.Widget.rect()) :: [ Drafter.Draw.Strip.t() ]
Draws the link as a single underlined strip.
Accepts either a t/0 or a raw props map, which is mounted first. The label is
:text, falling back to :url, and is wrapped in square brackets while focused
or hovered. rect is not consulted, so a label wider than the rect is neither
cropped nor padded. While hovered a :hover class and while focused a :focus
class are added to the computed style.
Callback implementation for Drafter.Widget.unmount/1.
@spec update(Drafter.Widget.props(), t()) :: t()
Folds fresh props into state, re-reading :text, :url, :style, :classes,
:app_module and :tooltip. :focused and :hovered are left alone.
iex> l = Drafter.Widget.Link.mount(%{text: "Old", url: "https://a.example"})
iex> Drafter.Widget.Link.update(%{text: "New"}, l).url
"https://a.example"
@spec update_props_from_mount(Drafter.Widget.props(), t(), keyword()) :: Drafter.Widget.props()
Narrows the props a re-render feeds to update/2 to :text, :url and
:app_module, so :style, :classes and :tooltip stay as mounted.