Tiptapex.Components (Tiptapex v0.1.2)

Copy Markdown View Source

HEEx function components for the Tiptap editor and viewer.

import Tiptapex.Components

<.tiptapex_editor id="body" value={@doc} upload_url={~p"/tiptapex/uploads"} />

<.tiptapex_viewer id="article" value={@article.body} />

Both components render a phx-update="ignore" root owned by the JS hooks shipped in this package (TiptapexEditor / TiptapexViewer); register the hooks in your app.js (see the Tiptapex module docs).

Sync modes

The editor supports two ways of getting the document back to the server:

  • sync={:push_event} (default) — the hook pushes the configured on_change event (default "tiptapex_change") with %{"json" => doc, "html" => html, "characters" => n} on every debounced change. Handle it in your LiveView and persist on an explicit save action. Do not trust the pushed "html" for display — re-render the JSON server-side with Tiptapex.Renderer.to_html/2.

  • sync={{:hidden_input, @form[:body]}} — the component renders a hidden input bound to the form field and the hook keeps it in sync with the document JSON, dispatching an input event so the form's phx-change fires. Pair the field with Tiptapex.Schema.Document in your Ecto schema and no custom handle_event is needed.

Summary

Functions

Pushes new content into a mounted editor from the server.

Pushes a new page setup into a mounted editor, leaving the content alone.

Renders the Tiptap editor.

Renders a Tiptap document read-only.

Functions

set_content(socket, id, doc)

Pushes new content into a mounted editor from the server.

{:noreply, Tiptapex.Components.set_content(socket, "body", restored_doc)}

The event is namespaced by the editor's id, so multiple editors in one LiveView never receive each other's content.

set_page(socket, id, page)

Pushes a new page setup into a mounted editor, leaving the content alone.

{:noreply, Tiptapex.Components.set_page(socket, "body", %{size: :legal})}

Useful when the page controls live in your LiveView rather than in the editor's own dialog — and the way to keep collaborators in step, since Yjs does not sync document-level attributes. Pass nil (or false) to turn page layout off.

tiptapex_editor(assigns)

Renders the Tiptap editor.

Examples

<.tiptapex_editor id="body" value={@body} on_change="editor_update" />

<.tiptapex_editor
  id="body"
  value={@body}
  upload_url={~p"/admin/uploads"}
  upload_scope={@article.id}
  collab={%{topic: "doc:" <> @article.slug, user: %{id: 1, name: "Ada", color: "#309"}}}
  toolbar={[:marks, :blocks, :lists, :history]}
  extensions={%{table: false, character_count_limit: 10_000}}
/>

Attributes

  • id (:string) (required) - logical editor id; also namespaces its events.

  • value (:map) - the Tiptap/ProseMirror JSON document (map or nil). Defaults to nil.

  • placeholder (:string) - Defaults to nil.

  • upload_url (:string) - endpoint for editor uploads; nil disables uploads entirely. Defaults to nil.

  • upload_scope (:any) - opaque value POSTed with each upload (e.g. the record id). Pass nil to declare "scope required but record not saved yet" — uploads stay blocked until it has a value. Leave as :none for unscoped uploads.

    Defaults to :none.

  • upload_scope_name (:string) - form field name for the scope. Defaults to "scope".

  • collab (:map) - enables realtime collaboration: %{topic: "...", socket_path: "/socket", user: %{id: ..., name: ..., email: ..., color: ...}}. Requires the host to build its hook with the CollabPlugin (see the collaboration guide).

    Defaults to nil.

  • toolbar (:any) - nil for the full default toolbar, false to hide it, a list of group atoms (:marks, :blocks, :align, :lists, :typography, :colors, :insert, :utilities, :history, :html) for an ordered subset, or a map for full config. The :html group toggles an editable HTML source view of the document; in collaborative editors the edits are applied through the shared Y.Doc so they propagate to peers.

    Defaults to nil.

  • extensions (:map) - per-feature switches forwarded to the JS buildExtensions/1, e.g. %{table: false, drag_handle: false, character_count_limit: 10_000}. %{html_view: false} disables the editable HTML source view.

    Defaults to nil.

  • labels (:map) - i18n label overrides for the toolbar, table menu and page dialog. Defaults to nil.

  • page (:any) - page layout — paper size, orientation, margins, running headers/footers and page numbering. nil (the default) uses whatever the document carries in attrs.page; false forces a continuous, unpaginated editor; true or a map (see Tiptapex.Page) forces this setup on the document, overriding what it carries. Pass it explicitly in collaborative editors — Yjs syncs the content but not the document node's attributes, so peers would otherwise each keep their own.

    Defaults to nil.

  • remount_key (:any) - bump this value to force a full client remount (e.g. after restoring a version). Defaults to nil.

  • on_change (:string) - event pushed on debounced updates (default "tiptapex_change"). Defaults to nil.

  • on_uploaded (:string) - event pushed after a successful upload (default "tiptapex_uploaded"). Defaults to nil.

  • sync (:any) - :push_event or {:hidden_input, form_field}. Defaults to :push_event.

  • debounce (:integer) - debounce for change events, in ms (default 400). Defaults to nil.

  • count_template (:string) - footer counter template, e.g. "{chars} caracteres · {words} palabras". Defaults to nil.

  • class (:any) - Defaults to nil.

  • Global attributes are accepted.

Slots

  • actions - rendered in the editor footer, next to the character count.

tiptapex_viewer(assigns)

Renders a Tiptap document read-only.

Server-side it renders safe HTML via Tiptapex.Renderer.to_html/2 — no raw/1, no trust in client HTML. With hydrate (the default) the TiptapexViewer hook replaces that fallback with a client-side Tiptap render, which reproduces interactive niceties (task list checkboxes, identical NodeViews) — visually both are the same.

Attributes

  • id (:string) - required when hydrate is true. Defaults to nil.

  • value (:map) - the Tiptap/ProseMirror JSON document. Defaults to nil.

  • hydrate (:boolean) - Defaults to true.

  • class (:any) - Defaults to nil.

  • renderer (:list) - options forwarded to Tiptapex.Renderer.to_html/2. Defaults to [].

  • page (:any) - page layout, as in tiptapex_editor/1. A document with a page setup is rendered as a stack of sheets when hydrated; the server-rendered fallback gets the paper's width and margins but no page breaks.

    Defaults to nil.

  • Global attributes are accepted.