PhoenixKitWeb.Components.Core.MarkdownEditor (phoenix_kit v1.7.71)

Copy Markdown View Source

Reusable markdown editor LiveComponent with cursor tracking, markdown formatting toolbar, component insertion, and unsaved changes protection.

Features

  • Monospace textarea optimized for markdown/code editing
  • Markdown formatting toolbar with selection-aware text manipulation
  • Cursor position tracking for inserting components at cursor
  • Optional toolbar for inserting images, videos, etc.
  • Save status indicator (saving/unsaved/saved)
  • Browser navigation protection for unsaved changes
  • Debounced content updates

Usage

<.live_component
  module={PhoenixKitWeb.Components.Core.MarkdownEditor}
  id="content-editor"
  content={@content}
  save_status={@save_status}
  show_formatting_toolbar={true}
  toolbar={[:image, :video]}
  on_change="content_changed"
  on_save="save_content"
  on_insert_component="insert_component"
/>

Formatting Toolbar

The formatting toolbar includes:

  • Headings: H1-H6 (adds # prefix to current line)
  • Inline styles: Bold, Italic, Strikethrough, Inline Code (wraps selection)
  • Links: Prompts for URL and wraps selection as link text
  • Lists: Bullet and numbered lists (adds prefix to current line)

When text is selected, formatting wraps the selection. When no text is selected, a placeholder is inserted and auto-selected for easy replacement.

Events Sent to Parent

The component sends messages to the parent LiveView via send/2:

  • {:editor_content_changed, %{content: content, editor_id: id}} - Content updated
  • {:editor_insert_component, %{type: :image | :video, editor_id: id}} - Toolbar button clicked

  • {:editor_save_requested, %{editor_id: id}} - Save button clicked

Commands from Parent

Use send_update/2 to send commands to the component:

# Insert text at cursor position
send_update(PhoenixKitWeb.Components.Core.MarkdownEditor,
  id: "content-editor",
  action: :insert_at_cursor,
  text: "<Image file_id=\"abc123\" />"
)

CSP Nonce

If your app uses Content Security Policy, pass the nonce:

<.live_component
  module={PhoenixKitWeb.Components.Core.MarkdownEditor}
  id="editor"
  content={@content}
  script_nonce={assigns[:csp_nonce] || ""}
/>