Xenia.Adapters.Tiptap (Xenia v0.1.1)

Copy Markdown View Source

<.tiptap>: a rich-text editor (Tiptap), through Xenia's official adapter.

Setup

Install the library in your app:

npm install @tiptap/core @tiptap/starter-kit @tiptap/extensions --prefix assets

Pass it to the adapter, and register it, in assets/js/app.js:

import { createTiptap } from "xenia/tiptap"

const tiptap = createTiptap({
    load: async () => {
      const [core, starterKit, extensions] = await Promise.all([
        import("@tiptap/core"),
        import("@tiptap/starter-kit"),
        import("@tiptap/extensions"),
      ])
      return {
        Editor: core.Editor,
        StarterKit: starterKit.default,
        CharacterCount: extensions.CharacterCount,
        Placeholder: extensions.Placeholder,
      }
    },
})

hooks: { ...colocatedHooks, ...createHooks({ Tiptap: tiptap }) },

Then import Xenia.Adapters.Tiptap in html_helpers, and render <.tiptap id="..."> with the props below. Every event becomes an on_<event> attribute; commands go through Xenia.push_to/4.

As a form field, field={@form[:x]} fills content and submits the component with the form.

The factory returns a plain adapter object: spread it to add or change props, commands and events, without copying the adapter.

The tag uses the adapter name "Tiptap". To register it under another name, render <.xenia adapter="..."> or declare your own tag.

Reference

Xenia's official adapter for Tiptap (v3): a rich-text editor that also works as a form field.

Props:

content      HTML string, or %{value, format: "html" | "json", revision}.
             As in monaco.js, a changed `revision` forces the server's
             content even over newer typing; otherwise, in a form, the
             editor's own earlier content coming back from validate is
             ignored.
format       "html" (default) or "json": what change events and the form
             field carry
editable     true (default) / false
placeholder  text shown while the editor is empty
limit        maximum number of characters (0 or nil = no limit)
toolbar      true for the default toolbar, a list of item names, or
             false. Items: bold, italic, underline, strike, code,
             heading1, heading2, heading3, paragraph, bullet_list,
             ordered_list, blockquote, code_block, horizontal_rule, link,
             undo, redo, separator
starter_kit  StarterKit configuration, e.g. %{heading: %{levels: [1, 2]},
             link: %{open_on_click: false}}. Changing it remounts.

Commands:

focus %{position?: "start" | "end" | "all"}, blur
set_content %{value, format?}     replace the content (not reported back)
clear
insert %{content}                 HTML or text at the cursor
run %{command, args?}             any Tiptap command on a focused chain,
                                  e.g. %{command: "toggleBold"} or
                                  %{command: "setLink", args: [%{href: "..."}]}

Events:

change  %{value, text, empty, characters, words}   debounced 300 ms
focus   %{}, blur %{}
error   %{source, message, code}

Form field: with field={@form[:body]}, the HTML (or JSON with format="json") is submitted with the form.

Tiptap is unstyled. The adapter adds minimal styles for the toolbar, placeholder and focus outline; style the content with your own CSS (for example Tailwind's prose class on the container).

Summary

Functions

tiptap(assigns)

Attributes

  • id (:string) - Stable DOM id; defaults to field.id. Defaults to nil.
  • field (Phoenix.HTML.FormField) - Phoenix form field for this component. Defaults to nil.
  • content (:any)
  • format (:string)
  • editable (:boolean)
  • placeholder (:string)
  • limit (:integer)
  • toolbar (:any)
  • starter_kit (:map)
  • on_change (:string) - LiveView event triggered when the adapter emits :change. Defaults to nil.
  • on_focus (:string) - LiveView event triggered when the adapter emits :focus. Defaults to nil.
  • on_blur (:string) - LiveView event triggered when the adapter emits :blur. Defaults to nil.
  • on_error (:string) - LiveView event triggered when the adapter emits :error. Defaults to nil.
  • shortcuts (:map) - Key combination => LiveView event, while focus is inside (see Xenia.Shortcuts). Defaults to %{}.
  • on_crash (:string) - LiveView event sent if the adapter throws (see Xenia.Component). Defaults to nil.
  • Global attributes are accepted.

Slots

  • loading - Shown until the island's first mount finishes.
  • error - Shown if the adapter throws; data-xenia-retry starts it again.