# `PhiaUi.Components.RichTextEditor`
[🔗](https://github.com/charlenopires/PhiaUI/blob/v0.1.17/lib/phia_ui/components/inputs/rich_text_editor.ex#L1)

Rich text editor component for PhiaUI.

Provides `rich_text_editor/1` — a `contenteditable`-based WYSIWYG editor
with a full formatting toolbar, `Phoenix.HTML.FormField` integration, and
changeset error display. Zero npm dependencies.

The editor is powered by the `PhiaRichTextEditor` JS hook, which uses:
- `document.execCommand()` for formatting commands (bold, italic, lists, etc.)
- The `Selection` API for active-state detection (highlighting toolbar buttons)
- A `MutationObserver` to sync the HTML content to a hidden `<input>` on change

## When to use

Use `rich_text_editor/1` for fields that need multi-line formatted content:

- Blog post / article body
- Email template editor
- Product description with emphasis and lists
- Knowledge base article
- Comment with basic formatting support

For plain text without formatting, use a regular `textarea` or `input`.

## Registration

Register the hook in `app.js`:

    import PhiaRichTextEditor from "./hooks/rich_text_editor"
    let liveSocket = new LiveSocket("/live", Socket, {
      hooks: { PhiaRichTextEditor }
    })

## Basic example

    <.form for={@form} phx-submit="publish">
      <.rich_text_editor
        field={@form[:body]}
        label="Article body"
        placeholder="Write your article here..."
        min_height="400px"
      />
      <.button type="submit">Publish</.button>
    </.form>

## Multiple editors on one page

Each editor is independent. Giving each a unique `field` is sufficient:

    <.rich_text_editor field={@form[:summary]} label="Summary" min_height="120px" />
    <.rich_text_editor field={@form[:body]}    label="Body"    min_height="400px" />

## Toolbar groups

| Group     | Buttons                                    |
|-----------|--------------------------------------------|
| Marks     | Bold, Italic, Underline, Strikethrough     |
| Blocks    | Heading 1, Heading 2, Heading 3, Paragraph |
| Lists     | Bullet List, Ordered List                  |
| Quotes    | Blockquote, Inline Code, Code Block        |
| Links     | Add Link, Remove Link                      |

Each button has `data-action` which the hook reads to dispatch the correct
`execCommand`. Active state is toggled via the `is-active` CSS class,
which the hook sets based on `document.queryCommandState()`.

## Changeset integration

The hook syncs the `contenteditable` HTML to a `<input type="hidden">` bound
to `field.name`. On `phx-submit`, the hidden input carries the HTML string
which the changeset receives:

    def changeset(post, attrs) do
      post
      |> cast(attrs, [:body])
      |> validate_required([:body])
      # Optionally sanitise HTML server-side with HtmlSanitizeEx:
      # |> update_change(:body, &HtmlSanitizeEx.basic_html/1)
    end

## Placeholder

The placeholder is implemented via CSS `::before` pseudo-element using
`data-placeholder` and the `is-empty` class toggled by the hook. This avoids
native `placeholder` which is not supported on `contenteditable` elements.

## Security note

The editor produces raw HTML. Always sanitise the stored HTML server-side
before rendering it back to other users. Consider `HtmlSanitizeEx` or
`Earmark` for sanitisation.

# `rich_text_editor`

Renders a rich text editor integrated with `Phoenix.HTML.FormField`.

The editor consists of:
1. An optional `<label>` linked to `field.id`
2. A bordered container with a formatting toolbar and the editable area
3. A `<input type="hidden">` bound to `field.name` (synced by the hook)
4. Changeset validation errors from `field.errors`

The `PhiaRichTextEditor` hook:
- Sets `contenteditable="true"` on the editor div on mount
- Loads `data-content` (the field's current value) as initial HTML
- Attaches `input` events to sync changes to the hidden input
- Attaches `click` events to toolbar buttons and dispatches `execCommand`
- Tracks active formatting via `queryCommandState` to toggle `is-active`

## Attributes

* `field` (`Phoenix.HTML.FormField`) (required) - A `Phoenix.HTML.FormField` from `@form[:field_name]`.
  Provides `id`, `name`, `value`, and `errors` for full form integration.
  The field value is loaded into the editor as initial HTML content.

* `label` (`:string`) - Label text rendered above the editor. Pass `nil` to omit the label. Defaults to `nil`.
* `placeholder` (`:string`) - Placeholder text shown when the editor is empty.
  Rendered via a CSS `::before` pseudo-element using `data-placeholder`
  and the `is-empty` class — not via the native `placeholder` attribute.

  Defaults to `nil`.
* `min_height` (`:string`) - Minimum height of the editable content area as a CSS value.
  The editor grows vertically beyond this minimum as content is added.
  Example values: `"200px"`, `"400px"`, `"50vh"`.

  Defaults to `"200px"`.
* `class` (`:string`) - Additional CSS classes for the outer wrapper div. Defaults to `nil`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
