# `Kino`
[🔗](https://github.com/livebook-dev/kino/blob/v0.19.0/lib/kino.ex#L1)

Client-driven interactive widgets for Livebook.

Kino is the library used by Livebook to render rich and interactive
outputs directly from your Elixir code.

## Getting started

Livebook is distributed with a set of interactive tutorials and
examples, including some that specifically focus on Kino. If you're
just getting started, going through these is highly recommended.

You can access these notebooks by starting Livebook and clicking
on "Learn" in the sidebar.

## Built-in kinos

Kino provides several built-in kinos. The `Kino.Shorts` module
provides a facade to access and use most of the Kinos in this
project, although you can also use their modules directly as
listed in the sidebar.

For user interactions, `Kino.Input` and `Kino.Control` provide
a set of widgets for entering data and capturing user events.
See the respective module documentation for examples.

Kino also provides facilities to aid debugging, such as
`Kino.Process` and a custom `dbg()` implementation that integrates
with Livebook.

## Custom kinos

Kino renders any data structure that implements the `Kino.Render`
protocol, falling back to the `Kernel.inspect/2` representation
whenever an implementation is not available. You can customize
how your own data structures are rendered by implementing the
`Kino.Render` protocol.

You can also implement your own kinos by writing custom JavaScript,
see `Kino.JS` and `Kino.JS.Live` for more details.

> #### Packaging {: .info}
>
> When publishing custom kinos and smart cells, please consider
> the following guidelines:
>
>   * prefix package name with `kino_`, usually followed by the
>     name of the integration, such as `kino_vega_lite`, `kino_ecto`
>
>   * namespace all modules under `KinoExample`, not `Kino.Example`.
>     Note that official packages maintained by the Livebook team
>     expose public APIs under `Kino.`, because they are essentially
>     direct extensions of `Kino` and we make sure no conflicting
>     modules exist. Unofficial packages should follow the usual
>     Elixir conventions with respect to module names
>

# `nothing`

```elixir
@type nothing() :: :&quot;do not show this result in output&quot;
```

# `animate`

```elixir
@spec animate(Enumerable.t() | pos_integer(), (term() -&gt; any())) :: nothing()
```

Renders a kino that periodically calls the given function
to render a new result.

The callback receives a stream element and should return a term
to be rendered.

This function uses `Kino.Frame` as the underlying kino.
It returns nothing (a non-printable result).

## Examples

An animation is created by turning a stream of values into
subsequent animation frames:

    Stream.interval(100)
    |> Stream.take(100)
    |> Kino.animate(fn i ->
      Kino.Markdown.new("**Iteration: `#{i}`**")
    end)

Alternatively an integer may be passed as a shorthand for
`Stream.interval/1`:

    # Render new Markdown every 100ms
    Kino.animate(100, fn i ->
      Kino.Markdown.new("**Iteration: `#{i}`**")
    end)

# `animate`

```elixir
@spec animate(
  Enumerable.t() | pos_integer(),
  state,
  (term(), state -&gt; {:cont, term(), state} | :halt)
) :: nothing()
when state: term()
```

A stateful version of `animate/2`.

The callback receives a stream element and the accumulated state
and it should return either of:

  * `{:cont, term_to_render, state}` - to continue

  * `:halt` - to no longer schedule callback evaluation

## Examples

This function is primarily useful to consume `Kino.Control` events:

    button = Kino.Control.button("Click")

    button
    |> Kino.Control.stream()
    |> Kino.animate(0, fn _event, counter ->
      new_counter = counter + 1
      md = Kino.Markdown.new("**Clicks: `#{new_counter}`**")
      {:cont, md, new_counter}
    end)

# `async_listen`

```elixir
@spec async_listen(Enumerable.t() | pos_integer(), (term() -&gt; any())) :: pid()
```

Same as `listen/2`, except each event is processed concurrently.

# `beam_paths`

```elixir
@spec beam_paths() :: [String.t()]
```

Returns the directories that contain `.beam` files for modules
defined in the notebook.

# `configure`

```elixir
@spec configure(keyword()) :: :ok
```

Configures Kino.

The supported options are:

  * `:inspect`

They are discussed individually in the sections below.

## Inspect

A keyword list containing inspect options used for printing
usual evaluation results. Defaults to pretty formatting with
a limit of 50 entries.

To show more entries, you configure a higher limit:

    Kino.configure(inspect: [limit: 200])

You can also show all entries by setting the limit to `:infinity`,
but keep in mind that for large data structures it is memory-expensive
and is not an advised configuration in this case. Instead prefer
the use of `IO.inspect/2` with `:infinity` limit when needed.

See `Inspect.Opts` for the full list of options.

# `inspect`

```elixir
@spec inspect(
  term(),
  keyword()
) :: term()
```

Inspects the given term as cell output.

This works essentially the same as `IO.inspect/2`, except it
always produces colored text and respects the configuration
set with `configure/1`.

Opposite to `render/1`, it does not attempt to render the given
term as a kino.

# `interrupt!`

```elixir
@spec interrupt!(:normal | :error, String.t()) :: no_return()
```

Interrupts evaluation with the given message.

This function raises a specific error to let Livebook know that
evaluation should be stopped. The error message and a `Continue`
button are shown to the user, who can then attempt to resolve the
source of the interrupt before resuming execution.

> #### Do not use interrupt inside listeners {: .warning}
>
> Since `interrupt!/2` aborts the execution, it cannot be used
> inside `Kino.listen/2` or other event listeners. In such cases,
> you can use `Kino.Frame` and render any messages directly within
> the frame, using `Kino.Text` or `Kino.Markdown`.

## Examples

    text =
      Kino.Input.text("Input")
      |> Kino.render()
      |> Kino.Input.read()

    if text == "" do
      Kino.interrupt!(:error, "Input required")
    end

    # This will not be run if the `interrupt!` is called above
    Kino.Markdown.new("**You entered:** #{text}")

# `listen`

```elixir
@spec listen(Enumerable.t() | pos_integer(), (term() -&gt; any())) :: pid()
```

Starts a process that consumes a stream with `fun` without blocking execution.

It returns the PID of the started process. The process can be terminated
with `Kino.terminate_child/1`.

Note that events are processed by `fun` sequentially. If you want
to process them concurrently, use `async_listen/2`.

## Examples

This function is primarily useful to consume `Kino.Control` events:

    Kino.Control.button("Greet")
    |> Kino.listen(fn event -> IO.inspect(event) end)

You can also merge multiple controls into a single stream. For example,
in order to merge them and tag each with a distinct event:

    button = Kino.Control.button("Hello")
    input = Kino.Input.checkbox("Check")

    stream = Kino.Control.tagged_stream([hello: button, check: input])

    Kino.listen(stream, fn
      {:hello, event} -> ...
      {:check, event} -> ...
    end)

Any other stream works as well:

    Stream.interval(100)
    |> Stream.take(10)
    |> Kino.listen(fn i -> IO.puts("Ping #{i}") end)

Finally, an integer may be passed as a shorthand for `Stream.interval/1`:

    Kino.listen(100, fn i -> IO.puts("Ping #{i}") end)

# `listen`

```elixir
@spec listen(
  Enumerable.t() | pos_integer(),
  state,
  (term(), state -&gt; {:cont, state} | :halt)
) :: pid()
when state: term()
```

A stateful version of `listen/2`.

The callback should return either of:

  * `{:cont, state}` - to continue

  * `:halt` - to stop listening

## Examples

    button = Kino.Control.button("Click")

    Kino.listen(button, 0, fn _event, counter ->
      new_counter = counter + 1
      IO.puts("Clicks: #{new_counter}")
      {:cont, new_counter}
    end)

# `nothing`

```elixir
@spec nothing() :: nothing()
```

Returns a special value that results in no visible output.

## Examples

This is especially handy when you wish to suppress the default output
of a cell. For instance, a cell containing this would normally result
in verbose response output:

    resp = Req.get!("https://example.org")

That output can be suppressed by appending a call to `nothing/0`:

    resp = Req.get!("https://example.org")
    Kino.nothing()

# `recompile`

```elixir
@spec recompile() :: :ok
```

Recompiles dependencies.

Once you have installed dependencies with `Mix.install/1`, this will
recompile any outdated path dependencies declared during the install.

> #### Reproducibility {: .warning}
>
> Keep in mind that recompiling dependency modules is **not** going
> to mark any cells as stale. This means that the given notebook
> state may no longer be reproducible. This function is meant as a
> utility when prototyping alongside a Mix project.

# `render`

```elixir
@spec render(term()) :: term()
```

Renders the given term as cell output.

This effectively allows any Livebook cell to have multiple
evaluation results.

# `start_child`

```elixir
@spec start_child(Supervisor.child_spec() | {module(), term()} | module()) ::
  DynamicSupervisor.on_start_child()
```

Starts a process under the Kino supervisor.

The process is automatically terminated when the current process
terminates or the current cell reevaluates.

If you want to terminate the started process, use
`terminate_child/1`. If you terminate the process manually,
the Kino supervisor might restart it if the child's `:restart`
strategy says so.

> #### Nested start {: .warning}
>
> It is not possible to use `start_child/1` while initializing
> another process started this way. In other words, you generally
> cannot call `start_child/1` inside callbacks such as `c:GenServer.init/1`
> or `c:Kino.JS.Live.init/2`. If you do that, starting the process
> will block forever.
>
> On creation, many kinos use `start_child/1` underneath, which means
> that you cannot use functions such as `Kino.DataTable.new/1` in
> `c:GenServer.init/1`. If you need to do that, you must either
> create the kinos beforehand and pass in the `GenServer` argument,
> or create them in `c:GenServer.handle_continue/2`.

# `start_child!`

```elixir
@spec start_child!(Supervisor.child_spec() | {module(), term()} | module()) :: pid()
```

Similar to `start_child/2` but returns the new pid or raises an error.

# `terminate_child`
*since 0.9.1* 

```elixir
@spec terminate_child(pid()) :: :ok | {:error, :not_found}
```

Terminates a child started with `start_child/1`.

Returns `:ok` if the child was found and terminated, or
`{:error, :not_found}` if the child was not found.

# `tmp_dir`

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

Returns a temporary directory that gets removed when the runtime
terminates.

---

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