View Source Kino.Output (Kino v0.10.0)

A number of output formats supported by Livebook.

Link to this section Summary

Types

A control widget.

Outputs placeholder.

Multiple outputs arranged in a grid.

An empty output that should be ignored whenever encountered.

A raw image in the given format.

An input field.

JavaScript powered output with dynamic data and events.

Data describing a JS output.

A JavaScript view definition.

Markdown content.

Plain text content.

IO text output, adjacent such outputs are treated as a whole.

t()

Livebook cell output may be one of these values and gets rendered accordingly.

Multiple outputs arranged into tabs.

Standalone text block visually matching stdout/0.

Link to this section Types

@type control() :: {:control, attrs :: control_attrs()}

A control widget.

All controls have the following properties:

  • :type - one of the recognised control types

  • :ref - a unique identifier

  • :destination - the process to send event messages to

On top of that, each control type may have additional attributes.

events

Events

All control events are sent to :destination as {:event, id, info}, where info is a map including additional details. In particular, it always includes :origin, which is an opaque identifier of the client that triggered the event.

@type control_attrs() ::
  %{
    type: :keyboard,
    ref: ref(),
    destination: Process.dest(),
    events: [:keyup | :keydown | :status]
  }
  | %{type: :button, ref: ref(), destination: Process.dest(), label: String.t()}
  | %{
      type: :form,
      ref: ref(),
      destination: Process.dest(),
      fields: [{field :: atom(), input_attrs()}],
      submit: String.t() | nil,
      report_changes: %{required(field :: atom()) => true},
      reset_on_submit: [field :: atom()]
    }
@type frame() :: {:frame, outputs :: [t()], frame_info()}

Outputs placeholder.

Frame with type :default includes the initial list of outputs. Other types can be used to update outputs within the given frame.

In all cases the outputs order is reversed, that is, most recent outputs are at the top of the stack.

@type frame_info() ::
  %{ref: frame_ref(), type: :default, placeholder: boolean()}
  | %{ref: frame_ref(), type: :replace | :append}
@type frame_ref() :: String.t()
@type grid() :: {:grid, outputs :: [t()], grid_info()}

Multiple outputs arranged in a grid.

@type grid_info() :: %{columns: pos_integer(), boxed: boolean()}
@type ignored() :: :ignored

An empty output that should be ignored whenever encountered.

@type image() :: {:image, content :: binary(), mime_type :: binary()}

A raw image in the given format.

pixel-data

Pixel data

Note that a special image/x-pixel MIME type is supported. The binary consists of the following consecutive parts:

  • height - 32 bits (unsigned big-endian integer)
  • width - 32 bits (unsigned big-endian integer)
  • channels - 8 bits (unsigned integer)
  • data - pixel data in HWC order

Pixel data consists of 8-bit unsigned integers. The number of channels can be either: 1 (grayscale), 2 (grayscale + alpha), 3 (RGB), or 4 (RGB + alpha).

@type input() :: {:input, attrs :: input_attrs()}

An input field.

All inputs have the following properties:

  • :type - one of the recognised input types

  • :ref - a unique identifier

  • :id - a persistent input identifier, the same on every reevaluation

  • :label - an arbitrary text used as the input caption

  • :default - the initial input value

  • :destination - the process to send event messages to

On top of that, each input type may have additional attributes.

@type input_attrs() ::
  %{
    type: :text,
    ref: ref(),
    id: input_id(),
    label: String.t(),
    default: String.t(),
    destination: Process.dest()
  }
  | %{
      type: :textarea,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: String.t(),
      monospace: boolean(),
      destination: Process.dest()
    }
  | %{
      type: :password,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: String.t(),
      destination: Process.dest()
    }
  | %{
      type: :number,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: number() | nil,
      destination: Process.dest()
    }
  | %{
      type: :url,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: String.t() | nil,
      destination: Process.dest()
    }
  | %{
      type: :select,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: term(),
      destination: Process.dest(),
      options: [{value :: term(), label :: String.t()}]
    }
  | %{
      type: :checkbox,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: boolean(),
      destination: Process.dest()
    }
  | %{
      type: :range,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: number(),
      destination: Process.dest(),
      min: number(),
      max: number(),
      step: number()
    }
  | %{
      type: :utc_datetime,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: NaiveDateTime.t() | nil,
      destination: Process.dest(),
      min: NaiveDateTime.t() | nil,
      max: NaiveDateTime.t() | nil
    }
  | %{
      type: :utc_time,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: Time.t() | nil,
      destination: Process.dest(),
      min: Time.t() | nil,
      max: Time.t() | nil
    }
  | %{
      type: :date,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: Date.t(),
      destination: Process.dest(),
      min: Date.t(),
      max: Date.t()
    }
  | %{
      type: :color,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: String.t(),
      destination: Process.dest()
    }
  | %{
      type: :image,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: nil,
      destination: Process.dest(),
      format: :rgb | :png | :jpeg,
      size: {pos_integer(), pos_integer()} | nil,
      fit: :match | :contain | :pad | :crop
    }
  | %{
      type: :audio,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: nil,
      destination: Process.dest(),
      format: :pcm_f32 | :wav,
      sampling_rate: pos_integer()
    }
  | %{
      type: :file,
      ref: ref(),
      id: input_id(),
      label: String.t(),
      default: String.t(),
      destination: Process.dest(),
      accept: [String.t()] | :any
    }
@type input_id() :: String.t()
@type js() :: {:js, info :: js_info()}

JavaScript powered output with dynamic data and events.

See Kino.JS and Kino.JS.Live for more details.

@type js_info() :: %{
  js_view: js_view(),
  export: nil | %{info_string: String.t(), key: nil | term()}
}

Data describing a JS output.

export

Export

The :export map describes how the output should be persisted. The output data is put in a Markdown fenced code block.

  • :info_string - used as the info string for the Markdown code block

  • :key - in case the data is a map and only a specific part should be exported

@type js_view() :: %{
  ref: ref(),
  pid: Process.dest(),
  assets: %{
    archive_path: String.t(),
    hash: String.t(),
    js_path: String.t(),
    cdn_url: String.t() | nil
  }
}

A JavaScript view definition.

JS view is a component rendered on the client side and possibly interacting with a server process within the runtime.

  • :ref - unique identifier

  • :pid - the server process holding the data and handling interactions

assets

Assets

The :assets map includes information about the relevant files.

  • :archive_path - an absolute path to a .tar.gz archive with all the assets

  • :hash - a checksum of all assets in the archive

  • :js_path - a relative asset path pointing to the JavaScript entrypoint module

  • :cdn_url - an absolute URL to a CDN directory where the asset files can be accessed from. Note that this URL is not guaranteed to be accessible, since it may be pointing to a private package

communication-protocol

Communication protocol

A client process should connect to the server process by sending:

{:connect, pid(), info :: %{ref: ref(), origin: term()}}

And expect the following reply:

{:connect_reply, payload, info :: %{ref: ref()}}

The server process may then keep sending one of the following events:

{:event, event :: String.t(), payload, info :: %{ref: ref()}}

The client process may keep sending one of the following events:

{:event, event :: String.t(), payload, info :: %{ref: ref(), origin: term()}}

The client can also send a ping message:

{:ping, pid(), metadata :: term(), info :: %{ref: ref()}}

And the server should respond with:

{:pong, metadata :: term(), info :: %{ref: ref()}}
@type markdown() :: {:markdown, binary()}

Markdown content.

@type plain_text() :: {:plain_text, binary()}

Plain text content.

Similar to markdown/0, but with no special markup.

@type ref() :: String.t()
@type stdout() :: {:stdout, binary()}

IO text output, adjacent such outputs are treated as a whole.

Supports ANSI escape codes.

@type t() ::
  ignored()
  | stdout()
  | text()
  | plain_text()
  | markdown()
  | image()
  | js()
  | frame()
  | tabs()
  | grid()
  | input()
  | control()

Livebook cell output may be one of these values and gets rendered accordingly.

@type tabs() :: {:tabs, outputs :: [t()], tabs_info()}

Multiple outputs arranged into tabs.

@type tabs_info() :: %{labels: [String.t()]}
@type text() :: {:text, binary()}

Standalone text block visually matching stdout/0.

Supports ANSI escape codes.

Link to this section Functions

@spec control(control_attrs()) :: t()

See control/0.

@spec frame([t()], frame_info()) :: t()

See frame/0.

@spec grid([t()], grid_info()) :: t()

See grid/0.

Link to this function

image(content, mime_type)

View Source
@spec image(binary(), binary()) :: t()

See image/0.

@spec input(input_attrs()) :: t()

See input/0.

Link to this function

inspect(term, opts \\ [])

View Source
@spec inspect(
  term(),
  keyword()
) :: t()

Returns text/0 with the inspected term.

@spec js(js_info()) :: t()

See js/0.

@spec markdown(binary()) :: t()

See markdown/0.

@spec plain_text(binary()) :: t()

See plain_text/0.

@spec random_ref() :: ref()

Generates a random binary identifier.

@spec tabs([t()], tabs_info()) :: t()

See tabs/0.

@spec text(binary()) :: t()

See text/0.