Kotoba.Components (Kotoba v0.5.0)

Copy Markdown View Source

Function components for the Kotoba editor and for rendered content.

import Kotoba.Components

<.form for={@form} phx-change="validate" phx-submit="save">
  <label id="post-body-label">Body</label>
  <.kotoba field={@form[:body]} id="post-body" label_id="post-body-label" />
</.form>

<.kotoba_content content={@post.body} />

The editor needs the Kotoba hook in the LiveSocket and the Kotoba CSS (see the README). It pushes kotoba:change only with change={true}.

Summary

Functions

Renders the rich-text editor for a form field.

Renders a Kotoba.Content as safe HTML.

Renders the app's own selection menu: the menu that floats over the selected text. Put it in the selection slot of kotoba/1

Renders a custom toolbar for an editor.

Returns the names of the toolbar commands, in toolbar order.

Functions

kotoba(assigns)

Renders the rich-text editor for a form field.

It renders:

  • a hidden input with the field's name and, as its value, the JSON of the field's value cast to Kotoba.Content (or of an empty document). The editor writes the document to it on every change, so a plain form submit posts it. It is outside the editor element, so a LiveView patch can update it;
  • the editor element, with phx-hook="Kotoba" and phx-update="ignore". The hook builds the toolbar and the editable area in it;
  • the LiveView file input of uploads, visually hidden, when uploads is given. The toolbar's attach button, a drop and a paste of files hand the files to it.

The editor always has an accessible name: aria-labelledby with label_id (the id of a visible label, the best choice), else aria-label with label, else the field name in words.

Attributes that are not declared (phx-target, …) go on the editor element. aria-describedby and aria-invalid go on the editable area (the textbox), and follow the field: a new value in a later render reaches it, and a value that goes away is removed. In a LiveComponent, give phx-target={@myself}, so that the editor's events go to the component.

The form posts the document, so a LiveView needs no editor event for a form. With change, the editor also pushes kotoba:change with %{"id", "doc", "v"} on each change (debounced), for example to save a draft; the LiveView must then handle it.

A change of readonly or change in a later render reaches the editor. To change the document after the first render, use Kotoba.Live.push_content/3: the editor reads the hidden input only when it mounts.

Attributes

  • field (Phoenix.HTML.FormField) (required) - the form field, for example @form[:body].
  • id (:string) - the id of the editor element. The default is the field's id with _editor. Defaults to nil.
  • label_id (:string) - the id of the element that labels the editor (aria-labelledby). Without it, the editor gets aria-label from label. Defaults to nil.
  • label (:string) - the accessible name when there is no label_id (aria-label). The default is the field name in words, for example "Body". Defaults to nil.
  • placeholder (:string) - the text of an empty editor. Defaults to nil.
  • collab (:map) - credentials from Kotoba.Collab.token/3; enables the optional collaboration bundle. Defaults to nil.
  • nodes (:list) - app nodes: {module, js_url} tuples, or JavaScript module URLs. Defaults to [].
  • features (:list) - the built-in features of the editor, see Kotoba.Features; every feature by default. Defaults to nil.
  • extensions (:list) - the URLs of the app's extension modules, see the Extensions guide; in the editor, after the features. Defaults to [].
  • prompts (:list) - the prompt list, see Kotoba.Prompts: a search callback, or options (label, spaces, items, insert...). Defaults to [].
  • assist (:any) - suggestions that the person asks for: a list of actions for the toolbar's Assist menu ([rewrite: "Rewrite"]), or true for no menu; the LiveView then handles kotoba:assist and kotoba:suggestion, see the Suggestions guide. Defaults to nil.
  • code_languages (:list) - the ids of the languages of the code language picker, see Kotoba.CodeLanguages; every language by default. Defaults to nil.
  • uploads (Phoenix.LiveView.UploadConfig) - an upload config, for example @uploads.attachments. Defaults to nil.
  • upload_label (:string) - the label of the file input. Defaults to "Attach files".
  • readonly (:boolean) - when true, the editor shows the document and cannot change it; a change in a later render reaches the editor. Defaults to false.
  • blank_lines (:atom) - :keep saves the blank lines a person types (empty paragraphs between blocks), as a word processor does; :collapse leaves them out of the saved document. Defaults to :keep. Must be one of :keep, or :collapse.
  • paste_markdown (:boolean) - when true, pasted plain text that reads as Markdown becomes rich text, read on the server by Kotoba.MarkdownPaste, which the editor renders with no code of the app; false renders no LiveComponent, for a template that cannot have one. Defaults to true.
  • change (:boolean) - when true, the editor pushes kotoba:change with the document on each change, and the LiveView (or the phx-target component) must handle it. Defaults to false.
  • debounce (:integer) - milliseconds between kotoba:change pushes; 300 when not given. Defaults to nil.
  • selection_menu (:any) - a menu over the selected text: true for the default commands (bold, italic, underline, strikethrough, code, highlight, link), or a list of commands, see toolbar_commands/0. The selection slot gives the app's own menu. Defaults to false.
  • class (:any) - classes for the wrapper element. Defaults to nil.
  • Global attributes are accepted. attributes for the editor element.

Slots

  • selection - the app's own selection menu, for example <.kotoba_selection_menu> with the app's icons.
  • toolbar - a custom toolbar, for example <.kotoba_toolbar>; the default toolbar has the commands of the editor's features, but subscript and superscript.

kotoba_content(assigns)

Renders a Kotoba.Content as safe HTML.

The cached :html of the content is used when its cache version is the current one (Kotoba.Content.cache_version/0), the policy is :default and no extra nodes are given: this is the HTML that Kotoba.Renderer made when the content was cast. In every other case, the document is rendered again with Kotoba.Renderer (a document that no longer parses renders as nothing). nil renders an empty wrapper.

Attributes

  • content (:any) (required) - a Kotoba.Content, or nil.
  • policy (:any) - :default or :untrusted, see Kotoba.Sanitizer. Defaults to :default.
  • nodes (:list) - extra node modules, {module, js_url} tuples, or JavaScript module URLs (the same list as kotoba/1; a URL has no module to render). Defaults to [].
  • class (:any) - classes for the wrapper, for example "prose". Defaults to nil.
  • Global attributes are accepted. attributes for the wrapper.

kotoba_selection_menu(assigns)

Renders the app's own selection menu: the menu that floats over the selected text. Put it in the selection slot of kotoba/1:

<.kotoba field={@form[:body]} id="post-body">
  <:selection>
    <.kotoba_selection_menu class="my-menu">
      <:button command="bold"><.icon name="hero-bold" /></:button>
      <:button command="italic"><.icon name="hero-italic" /></:button>
      <:button command="link" label="Add a link"><.icon name="hero-link" /></:button>
    </.kotoba_selection_menu>
  </:selection>
</.kotoba>

With no button slots, it renders one text button for each of commands. The commands, and what the editor does with the buttons, are the ones of kotoba_toolbar/1. The editor shows the menu over a selection of text, gives it the kotoba-selection-menu class and data-placement ("top" or "bottom"), and moves the focus to it with Alt+F10.

Attributes

  • commands (:list) - the commands, when there are no buttons. Defaults to ["bold", "italic", "underline", "strikethrough", "code", "highlight", "link"].
  • label (:string) - the accessible name of the menu. Defaults to "Selection formatting".
  • class (:any) - classes for the menu element. Defaults to nil.
  • Global attributes are accepted. attributes for the menu element.

Slots

  • button - Accepts attributes:
    • command (:string) (required)
    • label (:string)
    • class (:any)

kotoba_toolbar(assigns)

Renders a custom toolbar for an editor.

Inside the toolbar slot of kotoba/1, it needs no for. Elsewhere on the page, give the editor's id as for: the toolbar then has phx-update="ignore" (and the id <for>-toolbar), so that a LiveView patch does not undo the state that the editor puts on its buttons.

With no button slots, it renders one text button for each of commands. With button slots, it renders them, for example with the app's own icons:

<.kotoba_toolbar for="post-body">
  <:button command="bold"><.icon name="hero-bold" /></:button>
  <:button command="link" label="Add a link"><.icon name="hero-link" /></:button>
</.kotoba_toolbar>

The editor adds role="toolbar", the roving tabindex, aria-pressed and aria-disabled. The commands are the ones of toolbar_commands/0; or the command of an extension's control, "<extension>:<command>" (give it a label); another command raises ArgumentError. The editor hides the buttons of the features that it does not have (see Kotoba.Features), and the buttons of the table-* commands (the ones that act on the table at the selection) when the selection is not in a table, and the buttons of gallery, image-previous and image-next (the ones that act on the selected image) when no image is selected. code-language renders a <select>, the code language picker: the editor fills its options, and hides it when the selection is not in a code block. highlight opens the color palette of the editor (aria-haspopup="dialog").

Attributes

  • for (:string) - the id of the editor, when the toolbar is outside it. Defaults to nil.
  • commands (:list) - the commands, when there are no buttons. Defaults to ["bold", "italic", "underline", "strikethrough", "highlight", "code", "subscript", "superscript", "link", "h1", "h2", "h3", "h4", "quote", "bullet", "number", "check", "code-block", "rule", "table", "upload", "assist", "code-language", "table-row-before", "table-row-after", "table-column-before", "table-column-after", "table-header-row", "table-header-column", "table-delete-row", "table-delete-column", "table-delete", "gallery", "image-previous", "image-next", "undo", "redo"].
  • label (:string) - the accessible name of the toolbar. Defaults to "Formatting".
  • class (:any) - classes for the toolbar element. Defaults to nil.
  • Global attributes are accepted. attributes for the toolbar element.

Slots

  • button - Accepts attributes:
    • command (:string) (required)
    • label (:string)
    • class (:any)

toolbar_commands()

@spec toolbar_commands() :: [String.t()]

Returns the names of the toolbar commands, in toolbar order.

Examples

iex> "bold" in Kotoba.Components.toolbar_commands()
true