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
Renders the rich-text editor for a form field.
It renders:
- a hidden input with the field's
nameand, as its value, the JSON of the field's value cast toKotoba.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"andphx-update="ignore". The hook builds the toolbar and the editable area in it; - the LiveView file input of
uploads, visually hidden, whenuploadsis 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 tonil.label_id(:string) - the id of the element that labels the editor (aria-labelledby). Without it, the editor getsaria-labelfromlabel. Defaults tonil.label(:string) - the accessible name when there is nolabel_id(aria-label). The default is the field name in words, for example "Body". Defaults tonil.placeholder(:string) - the text of an empty editor. Defaults tonil.collab(:map) - credentials from Kotoba.Collab.token/3; enables the optional collaboration bundle. Defaults tonil.nodes(:list) - app nodes:{module, js_url}tuples, or JavaScript module URLs. Defaults to[].features(:list) - the built-in features of the editor, seeKotoba.Features; every feature by default. Defaults tonil.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, seeKotoba.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"]), ortruefor no menu; the LiveView then handleskotoba:assistandkotoba:suggestion, see the Suggestions guide. Defaults tonil.code_languages(:list) - the ids of the languages of the code language picker, seeKotoba.CodeLanguages; every language by default. Defaults tonil.uploads(Phoenix.LiveView.UploadConfig) - an upload config, for example@uploads.attachments. Defaults tonil.upload_label(:string) - the label of the file input. Defaults to"Attach files".readonly(:boolean) - whentrue, the editor shows the document and cannot change it; a change in a later render reaches the editor. Defaults tofalse.blank_lines(:atom) -:keepsaves the blank lines a person types (empty paragraphs between blocks), as a word processor does;:collapseleaves them out of the saved document. Defaults to:keep. Must be one of:keep, or:collapse.paste_markdown(:boolean) - whentrue, pasted plain text that reads as Markdown becomes rich text, read on the server byKotoba.MarkdownPaste, which the editor renders with no code of the app;falserenders no LiveComponent, for a template that cannot have one. Defaults totrue.change(:boolean) - whentrue, the editor pusheskotoba:changewith the document on each change, and the LiveView (or thephx-targetcomponent) must handle it. Defaults tofalse.debounce(:integer) - milliseconds betweenkotoba:changepushes; 300 when not given. Defaults tonil.selection_menu(:any) - a menu over the selected text:truefor the default commands (bold, italic, underline, strikethrough, code, highlight, link), or a list of commands, seetoolbar_commands/0. Theselectionslot gives the app's own menu. Defaults tofalse.class(:any) - classes for the wrapper element. Defaults tonil.- 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, butsubscriptandsuperscript.
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) - aKotoba.Content, ornil.policy(:any) -:defaultor:untrusted, seeKotoba.Sanitizer. Defaults to:default.nodes(:list) - extra node modules,{module, js_url}tuples, or JavaScript module URLs (the same list askotoba/1; a URL has no module to render). Defaults to[].class(:any) - classes for the wrapper, for example"prose". Defaults tonil.- Global attributes are accepted. attributes for the wrapper.
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 tonil.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 tonil.- Global attributes are accepted. attributes for the toolbar element.
Slots
button- Accepts attributes:command(:string) (required)label(:string)class(:any)
@spec toolbar_commands() :: [String.t()]
Returns the names of the toolbar commands, in toolbar order.
Examples
iex> "bold" in Kotoba.Components.toolbar_commands()
true