ReadyEditor ReadyEditor
docs/ui-core.md

UI Core & Plugin System

The ReadyEditorUI global object provides the plugin registration system, modal manager, and toolbar utilities. It is loaded automatically by the loader before any plugins run.


ReadyEditorUI.registerPlugin(nameOrMeta, fn)

Registers a plugin.

Simple form:

ReadyEditorUI.registerPlugin('myPlugin', function(ctx) {
  // ...
});

With metadata:

ReadyEditorUI.registerPlugin(
  { name: 'myPlugin', group: 'Insert', order: 50, deps: [] },
  function(ctx) { /* … */ }
);

Plugins only run when their name appears in the features list returned by the init endpoint. This is how plan-based feature gating works.


ReadyEditorUI.enhanceInstance(instance, serverConfig?)

Manually wraps a bare EditorInstance with toolbar, status bar, and plugins. The loader calls this automatically — you only need it for advanced custom integrations.


ReadyEditorUI.ModalManager

ModalManager.openFormModal(config)

Opens a form dialog.

Config:

Field Type Description
title string Modal title
fields array Form fields (see below)
confirmText string Submit button label (default "OK")
cancelText string Cancel button label (default "Cancel")
onSubmit(values) function Called with { fieldName: value } on submit
onCancel() function Called on cancel or close

Field object:

Field Type Description
name string Field name (key in values)
label string Label text
type string text, number, textarea, password
placeholder string Placeholder text
value string Default value
rows number Textarea rows (for textarea type)
helpText string Help text shown below the field

Example:

ReadyEditorUI.ModalManager.openFormModal({
  title: 'Insert Link',
  fields: [
    { name: 'url',  label: 'URL',       type: 'text', placeholder: 'https://…' },
    { name: 'text', label: 'Link text', type: 'text' },
  ],
  onSubmit: function(values) {
    ctx.instance.insertHTML(
      '<a href="' + ctx.utils.escapeHtml(values.url) + '">' +
      ctx.utils.escapeHtml(values.text || values.url) + '</a>'
    );
  },
});

ModalManager.close()

Closes the currently open modal.


ReadyEditorUI.utils

Utility functions available to all plugins via ctx.utils.

utils.escapeHtml(str) → string

Escapes &, <, >, ", ' for safe HTML insertion.

utils.escapeRegExp(str) → string

Escapes regex special characters.

utils.addButton(toolbar, label, title, onClick) → HTMLElement

Adds a button to the toolbar.

  • label — button content (HTML allowed, so you can use icon markup like <i class="ri-bold"></i>)
  • title — tooltip text
  • onClick — click handler

utils.addSelect(toolbar, options, title, onChange) → HTMLElement

Adds a <select> dropdown to the toolbar.

utils.addSelect(toolbar, [
  { value: 'p',  label: 'Paragraph' },
  { value: 'h1', label: 'Heading 1' },
  { value: 'h2', label: 'Heading 2' },
], 'Format', function(value) {
  instance.execCommand('formatBlock', '<' + value + '>');
});

utils.addColorInput(toolbar, title, onInput) → HTMLElement

Adds a color picker to the toolbar. onInput receives the hex color string.

utils.addSeparator(toolbar)

Adds a visual separator to the toolbar.


Plugin context object (ctx)

Every plugin function receives a context object:

Property Type Description
instance EditorInstance The editor instance
toolbar HTMLElement Toolbar container
statusbar HTMLElement Status bar container
container HTMLElement Outer editor container
ModalManager object Modal manager
serverConfig object Init endpoint response
utils object UI utility functions (see above)

DOM structure

<div class="readyeditor-container">
  <div class="readyeditor-toolbar">
    <div class="readyeditor-toolbar-group" data-re-group="formatting">
      <!-- Plugin buttons for this group -->
    </div>
    <!-- … more groups … -->

    <!-- Overflow wrapper — only present when overflow is enabled (default) -->
    <div class="readyeditor-toolbar-overflow">
      <button class="readyeditor-toolbar-overflow-btn readyeditor-btn">More ▾</button>
      <div class="readyeditor-toolbar-overflow-menu">
        <!-- Groups moved here when toolbar wraps or when pinned via overflowGroups -->
      </div>
    </div>
  </div>
  <div class="readyeditor-root" contenteditable="true">
    <!-- Editor content -->
  </div>
  <div class="readyeditor-statusbar">
    <!-- Status bar (e.g. word count) -->
  </div>
</div>

The overflow wrapper is absent when data-toolbar-overflow="off" / ui.overflow = false.

CSS classes

Container/layout: .readyeditor-container, .readyeditor-toolbar, .readyeditor-statusbar

Toolbar groups: .readyeditor-toolbar-group, .readyeditor-toolbar-group--overflowed (applied while a group is in the overflow menu)

Toolbar overflow: .readyeditor-toolbar-overflow, .readyeditor-toolbar-overflow-btn, .readyeditor-toolbar-overflow-menu, .is-open (on overflow wrapper when menu is visible)

Toolbar controls: .readyeditor-btn, .readyeditor-btn-active, .readyeditor-separator, .readyeditor-select, .readyeditor-color-input

Modals: .readyeditor-modal-overlay, .readyeditor-modal, .readyeditor-modal-header, .readyeditor-modal-title, .readyeditor-modal-close, .readyeditor-modal-body, .readyeditor-modal-footer, .readyeditor-modal-form, .readyeditor-modal-field, .readyeditor-modal-label, .readyeditor-modal-input, .readyeditor-modal-textarea, .readyeditor-modal-btn, .readyeditor-modal-btn-primary, .readyeditor-modal-help


Selection preservation

Toolbar buttons execute their action on pointerdown/mousedown and call preventDefault() to prevent the browser from moving focus away from the editor — which would collapse the text selection before the action runs. Keep this in mind when building custom toolbar controls.


Version

ReadyEditorUI.version  // e.g. "2.0.0"