# `Expresso.Element`
[🔗](https://github.com/rellen/expresso/blob/main/lib/expresso/element.ex#L1)

The behaviour of an element of a slide

`use Expresso.Element` declares this behaviour, so the compiler gives a
warning for an element module without `get_assigns/1` or `render/1`. It
also imports Temple and `Expresso.Component` for the render function of the
element. The module also holds the functions of the `class` option, which
each element and each slide takes.

# `kind`

```elixir
@type kind() :: {module() | nil, String.t(), String.t(), morph_content() | nil}
```

A kind of element: its module, the class of its root tag, its name, and the
content that the auto morph compares, or `nil` for a kind that the morph
does not use. The heading of a slide comes from the template, so it has no
module.

# `morph_content`

```elixir
@type morph_content() ::
  :text | :source | :file | :drawing | :svg | :shape | :language | :label
```

The content that the auto morph compares for two elements of one kind.
`Expresso.Morph` tells what each one is.

# `get_assigns`

```elixir
@callback get_assigns(element :: struct()) :: map()
```

Make the assigns of the render function from the struct of an element

The key `overlay` holds the attributes from
`Expresso.Overlay.Render.attributes/1`. `assigns/1` adds the key `class`.

# `render`

```elixir
@callback render(assigns :: map()) :: Phoenix.HTML.safe()
```

Make the HTML of an element from its assigns

The root tag gets the attributes of `@overlay` with `rest!: @overlay`, and
the classes of the element with `classes/2`.

# `assigns`

```elixir
@spec assigns(struct()) :: map()
```

Return the assigns of an element for its render function

The function calls `get_assigns/1` of the module of the element, and it
adds the `class` field of the element under the key `class`.

# `box_style`

```elixir
@spec box_style(String.t() | nil, String.t() | nil) :: [{String.t(), String.t()}]
```

Return the style attribute of the box of an embed or of a video

The box takes the `width` option and the `aspect` option. An element
without both gets no attribute.

    iex> Expresso.Element.box_style("60%", "4/3")
    [{"style", "--embed-width: 60vw; --embed-aspect: 4/3"}]
    iex> Expresso.Element.box_style(nil, nil)
    []

# `class`

```elixir
@spec class(term()) :: {:ok, String.t()} | {:error, String.t()}
```

Make sure that a `class` option holds CSS class names

This function is the custom type of the option. The value is one name or
more, with one space or more between two names, such as `"dense wide"`.
The function returns the names with one space between two names.

    iex> Expresso.Element.class("dense  wide")
    {:ok, "dense wide"}

    iex> {:error, _message} = Expresso.Element.class("2col")

# `classes`

```elixir
@spec classes(String.t(), String.t() | nil) :: String.t()
```

Join the class of the theme and the classes of the `class` option

    iex> Expresso.Element.classes("code", "dense")
    "code dense"

    iex> Expresso.Element.classes("code", nil)
    "code"

# `kinds`

```elixir
@spec kinds() :: [kind()]
```

Return each kind of element that the presenter script finds by the class
of its root tag

The script finds the kind of an element from the first kind in the list
whose class the element has, and the layout check measures each kind.
`Expresso.Presenter.Schema` writes the class and the name of each kind into
`assets/src/schema.ts`. `Expresso.Morph` gives a signature to each element
of a kind with a content. The list has no item of a list, no row of a table
and no spacer, because each is a part of an element or shows nothing.

# `name`

```elixir
@spec name(module()) :: String.t()
```

Return the name of the entity of a module of an element, for an error

The name is the last part of the module, with underscores. The module of
the `tree` entity is `Expresso.Element.Hierarchy`, because
`Expresso.Element.Tree` holds the walks over the elements.

    iex> Expresso.Element.name(Expresso.Element.TextBox)
    "text_box"

    iex> Expresso.Element.name(Expresso.Element.Hierarchy)
    "tree"

# `viewport_unit`

```elixir
@spec viewport_unit(String.t()) :: String.t()
```

Write a width in percent as a viewport unit

A value that is one number and a percent sign becomes the same number in
`vw`, and each other value comes back as it is. A slide takes the full width
of the screen and of the page, so a percentage of the slide is a viewport
unit. `Expresso.Element.Image` gives the reasons.

    iex> Expresso.Element.viewport_unit("60%")
    "60vw"
    iex> Expresso.Element.viewport_unit(".5%")
    ".5vw"
    iex> Expresso.Element.viewport_unit("calc(50% + 10px)")
    "calc(50% + 10px)"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
