Coelho.Kino (coelho v0.18.0)

Copy Markdown View Source

A Coelho editor in a Livebook cell.

editor = Coelho.Kino.new()

It is the same editor a LiveView renders — the same component, the same hook, the same schema on both sides — so what a notebook shows is what an application gets. Read what was typed, as the document that would be stored:

Coelho.Kino.read(editor)

React to every change:

Kino.listen(editor, fn %{type: :change, document: document} ->
  IO.inspect(Coelho.to_text(document))
end)

Every change is validated on the server before it is kept, exactly as a form submission would be: a document the schema refuses is never stored, and the editor that sent it is put back to the last valid one.

Requires kino and phoenix_live_view, both optional dependencies of Coelho:

Mix.install([:coelho, :kino, :phoenix_live_view])

The editor has no uploads: a LiveView's upload channel is what carries them, and a notebook has none.

One writer at a time

Each change carries the whole document, and the last one to arrive is what is kept. Two people typing in the same editor — two tabs on one session, or a collaborator in Livebook — overwrite each other, and the other editors are not told of a change until they reconnect. Writing together is collaboration proper, which Coelho does not do yet.

Summary

Functions

A new editor.

The document in the editor, as it would be stored.

Replaces the document in the editor.

Types

event()

@type event() ::
  %{type: :change, document: map()}
  | %{type: :hook, event: String.t(), payload: term()}

An event emitted to Kino.listen/2 and Kino.Control.stream/1.

Functions

new(opts \\ [])

@spec new(keyword()) :: Kino.JS.Live.t()

A new editor.

Options

  • :schema — the Coelho.Schema to edit under. Coelho.Schema.default/0 when omitted
  • :value — the document to start from, validated against the schema; an empty document when omitted

Any other option is an attribute of Coelho.LiveView.coelho_editor/1 — :toolbar, :labels, :placeholder, :maxlength — passed through as given. :suggest passes through too, but only opens and closes the list: the queries arrive as :hook events, and nothing here inserts a choice.

Raises ArgumentError for a :value the schema refuses.

read(kino)

@spec read(Kino.JS.Live.t()) :: map()

The document in the editor, as it would be stored.

set(kino, document)

@spec set(Kino.JS.Live.t(), map()) :: :ok | {:error, [Coelho.Document.Error.t()]}

Replaces the document in the editor.

Validated like everything else: {:error, errors} leaves the editor as it was.