Skip to main content

API reference

Attributes​

AttributeValuesDescription
readonlybooleanDisables editing and hides the toolbar.
placeholderstringShown while empty.
dirrtl | ltr | autoBase direction (default auto; paragraphs still auto-detect from their first strong character).
localeen | arToolbar language (default en).
toolbarcomma-separated groups or noneGroups: history, block, font, inline, list, align, direction, insert.
fontscomma-separated font familiesSimple form of the toolbar font list, e.g. fonts="Amiri, Tahoma, Arial". Use the fonts property for labels and full font stacks.

Properties​

PropertyTypeDescription
valuestring | nullSerialized Lexical editor state JSON (get/set; canonical persistence format).
initialHtmlstring | nullHTML applied on first init when no value was set.
fontsFontOption[] | nullToolbar font list ({ label, family }[]). Replaces the defaults; spread the exported DEFAULT_FONTS to extend them instead. null restores the defaults.
editorLexicalEditorEscape hatch for advanced use (custom commands, transforms, …). Throws before first connect.

Methods​

MethodDescription
getJSON()Current state as serialized Lexical JSON.
getHTML()Current content as HTML.
setValue(json)Replace content from serialized JSON.
setHTML(html)Replace content from HTML.
clear()Empty the editor.
focus()Focus the editable area.
insertHijriDate(date?, format?)Insert a Hijri date token at the caret (defaults to today).

Events​

EventDetailNotes
change{ json: string; isEmpty: boolean }Debounced ~150 ms. HTML is not included (exporting walks the whole document) — call getHTML() on save/blur instead.
rte-ready—Fired once after the editor initializes.

Dawat content blocks​

Ayat block​

Toolbar ۞ button or the block dropdown. Renders centered, enlarged, RTL, in the Arabic font. Exports as:

<blockquote data-spez-type="ayat" dir="rtl">…</blockquote>

Transliteration pair​

Toolbar ت/t button inserts a two-line unit — an Arabic line and a Latin (transliteration) line:

<div data-spez-type="translit-pair">
<p data-role="arabic" dir="rtl">العلم نور</p>
<p data-role="latin" dir="ltr">al-ilmu noor</p>
</div>

Editing behavior (the pair is self-normalizing — it always has exactly one Arabic + one Latin line):

  • Enter in the Arabic line → jumps to the Latin line; Enter in the Latin line → exits below the pair
  • Backspace at the start of the Latin line → moves the caret to the Arabic line (never merges the two lines)
  • Backspace at the start of the Arabic line → unwraps the pair into plain paragraphs
  • Backspace / Delete in an all-empty pair → removes the whole pair
  • Switching block type from the dropdown while inside a pair converts the pair into the chosen block

Hijri date token​

Toolbar 📅 button. Atomic (deletes/moves as one unit), backed by @spezutil/hijri-core — it stores the actual {year, month, day}, not just text. Exports as:

<time data-spez-hijri="1446-9-17" data-spez-format="D MMMM YYYY">17 Ramadan al-Moazzam 1446</time>

Programmatic insertion:

editor.insertHijriDate({ year: 1446, month: 9, day: 17 }, "D MMMM YYYY");

If @spezutil/hijri-datepicker is loaded on the page, the toolbar button opens a date-picker popover instead of inserting today's date directly.

Font selector​

The toolbar's font group applies a font to the selected text (stored as an inline font-family style; survives HTML export/import). The default list is the embedded Amiri plus safe cross-platform stacks. Configure it with the fonts property:

import { DEFAULT_FONTS } from "@spezutil/richtext-editor";

editor.fonts = [
...DEFAULT_FONTS,
{ label: "Scheherazade", family: '"Scheherazade New", serif' },
];

Custom fonts must be loaded on the page (your own @font-face or a font service) — the editor only applies the font-family value.

Theming​

All styling hangs off CSS custom properties on the host element:

spez-richtext {
--rte-accent: #7c3aed;
--rte-font-family-arabic: "My Arabic Font", serif;
--rte-ayat-font-size: 1.75em;
}
PropertyDefaultApplies to
--rte-font-family"Amiri", system-ui, sans-serifBase text (Amiri only binds to Arabic codepoints).
--rte-font-family-arabic"Amiri", "Traditional Arabic", serifRTL blocks, ayat.
--rte-accent#0b7d3eButtons, links, focus states.
--rte-bg / --rte-fg#ffffff / #1f2933Editor surface.
--rte-muted#6b7280Placeholder, secondary text.
--rte-border#d9dee4Borders.
--rte-radius8pxCorner radius.
--rte-toolbar-bg#f7f8f9Toolbar background.
--rte-ayat-font-size1.5emAyat block text.
--rte-translit-colorvar(--rte-muted)Latin transliteration line.

Notes​

  • Light DOM. Unlike typical Web Components, <spez-richtext> renders in light DOM: Lexical's selection handling relies on window.getSelection(), which does not work inside shadow roots (facebook/lexical#8125). Styles are scoped under the spez-rte- class prefix and injected once per document, so they won't collide with your CSS.
  • Bundle size. The embedded Amiri font adds ~500 KB (base64) to the bundle. In exchange the component is fully self-contained — no font hosting, no asset-path configuration, no FOUT on Arabic text.
  • Font license. The embedded Amiri typeface is © its authors, redistributed under the SIL Open Font License 1.1; the license text ships in the repository at assets/fonts/OFL-Amiri.txt.
  • Lexical versions. lexical and all @lexical/* packages are regular dependencies, version-matched. If your app also uses Lexical directly, keep it deduped to a single copy — two copies break Lexical's node identity checks.