← All @molecule/* packages · App templates
@molecule/app-rich-textFeature · rich-text · App (browser) · v1.0.2 · Apache-2.0
Rich text editing and formatting
npm install @molecule/app-rich-text@molecule/app-rich-text is a ready-made rich-text feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.
import { createEditor, htmlToValue, setProvider } from '@molecule/app-rich-text'
import type { TextChangeData } from '@molecule/app-rich-text'
import { provider as quillProvider } from '@molecule/app-rich-text-quill'
// Wire the provider once at app startup
setProvider(quillProvider)
// Create an editor instance attached to a DOM container
const container = document.getElementById('editor')!
const editor = createEditor({ container, placeholder: 'Start typing…', toolbar: 'standard' })
editor.on<TextChangeData>('text-change', ({ value }) => console.log(value.text))
// Convert existing HTML into the editor
editor.setValue(htmlToValue('<p>Hello <strong>world</strong></p>'))Providers (1): @molecule/app-rich-text-quill
Works with: @molecule/app-bond
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Rich text editor interface for molecule.dev.
Provides a unified API for rich text editing that can be backed by
different editor implementations. Wire a provider with setProvider();
@molecule/app-rich-text-quill is the shipped production bond.
import { createEditor, htmlToValue, setProvider } from '@molecule/app-rich-text'
import type { TextChangeData } from '@molecule/app-rich-text'
import { provider as quillProvider } from '@molecule/app-rich-text-quill'
// Wire the provider once at app startup
setProvider(quillProvider)
// Create an editor instance attached to a DOM container
const container = document.getElementById('editor')!
const editor = createEditor({ container, placeholder: 'Start typing…', toolbar: 'standard' })
editor.on<TextChangeData>('text-change', ({ value }) => console.log(value.text))
// Convert existing HTML into the editor
editor.setValue(htmlToValue('<p>Hello <strong>world</strong></p>'))
feature
npm install @molecule/app-rich-text @molecule/app-bond dompurify
EditorOptionsConfiguration options for creating a new rich text editor instance.
interface EditorOptions {
/**
* Container element.
*/
container: HTMLElement
/**
* Initial value.
*/
value?: RichTextValue
/**
* Placeholder text.
*/
placeholder?: string
/**
* Toolbar configuration key or custom config.
*/
toolbar?: string | ToolbarConfig
/**
* Read-only mode.
*/
readOnly?: boolean
/**
* Custom formats to register.
*/
formats?: FormatType[]
/**
* Theme name.
*/
theme?: string
/**
* Additional modules/plugins configuration.
*/
modules?: Record<string, unknown>
}
FormatButtonFormat button with options.
interface FormatButton {
/**
* Format type.
*/
type: FormatType
/**
* Options for the format (e.g., header levels, colors).
*/
options?: (string | number | boolean)[]
}
RichTextEditorRich text editor instance with methods for content manipulation, formatting, and event handling.
interface RichTextEditor {
/**
* Gets the current content value.
*/
getValue(): RichTextValue
/**
* Sets the content value.
*/
setValue(value: RichTextValue): void
/**
* Gets the plain text content.
*/
getText(): string
/**
* Gets the HTML content.
*/
getHTML(): string
/**
* Gets the content length.
*/
getLength(): number
/**
* Inserts text at the current cursor position.
*/
insertText(text: string, index?: number): void
/**
* Inserts HTML at the current cursor position.
*/
insertHTML(html: string, index?: number): void
/**
* Inserts an embed (image, video, etc.).
*/
insertEmbed(type: string, value: unknown, index?: number): void
/**
* Deletes content.
*/
deleteText(index: number, length: number): void
/**
* Formats text.
*/
format(format: FormatType, value?: unknown): void
/**
* Formats text at a specific range.
*/
formatText(index: number, length: number, format: FormatType, value?: unknown): void
/**
* Removes formatting.
*/
removeFormat(index: number, length: number): void
/**
* Gets the current selection.
*/
getSelection(): SelectionRange | null
/**
* Sets the selection.
*/
setSelection(index: number, length?: number): void
/**
* Focuses the editor.
*/
focus(): void
/**
* Blurs the editor.
*/
blur(): void
/**
* Checks if the editor has focus.
*/
hasFocus(): boolean
/**
* Enables the editor.
*/
enable(): void
/**
* Disables the editor.
*/
disable(): void
/**
* Checks if the editor is enabled.
*/
isEnabled(): boolean
/**
* Subscribes to editor events.
*/
on<T>(event: EditorEvent, handler: EditorEventHandler<T>): () => void
/**
* Removes event handler.
*/
off<T>(event: EditorEvent, handler: EditorEventHandler<T>): void
/**
* Gets the underlying editor instance (for advanced usage).
*/
getEditorInstance(): unknown
/**
* Destroys the editor.
*/
destroy(): void
}
RichTextProviderRich text editor provider interface for creating editors and converting content formats.
interface RichTextProvider {
/**
* Create a new rich text editor instance attached to a container element.
* @returns A RichTextEditor instance for controlling the editor.
*/
createEditor(options: EditorOptions): RichTextEditor
/**
* Get the name of this rich text provider (e.g., 'quill', 'tiptap', 'slate').
* @returns The provider name string.
*/
getName(): string
/**
* Get the available toolbar configuration presets (e.g., 'minimal', 'standard', 'full').
* @returns A map of preset names to their ToolbarConfig definitions.
*/
getToolbarPresets(): Record<string, ToolbarConfig>
/**
* Convert an HTML string to the editor's internal rich text format.
* @returns A RichTextValue in the provider's internal format.
*/
htmlToValue(html: string): RichTextValue
/**
* Convert a plain text string to the editor's internal rich text format.
* @returns A RichTextValue in the provider's internal format.
*/
textToValue(text: string): RichTextValue
/**
* Create an empty rich text value suitable for initializing an editor.
* @returns An empty RichTextValue.
*/
createEmptyValue(): RichTextValue
}
RichTextValueRich text content value.
interface RichTextValue {
/**
* Plain text content.
*/
text: string
/**
* HTML content.
*/
html: string
/**
* Delta/JSON representation (if supported by the editor).
*/
delta?: unknown
}
SelectionChangeDataData emitted when the editor selection changes.
interface SelectionChangeData {
/**
* New selection range.
*/
range: SelectionRange | null
/**
* Previous selection range.
*/
previousRange: SelectionRange | null
/**
* Source of the change.
*/
source: 'user' | 'api' | 'silent'
}
SelectionRangeSelection range in the editor.
interface SelectionRange {
/**
* Start index.
*/
index: number
/**
* Length of selection.
*/
length: number
}
TextChangeDataData emitted when the editor content changes.
interface TextChangeData {
/**
* New value.
*/
value: RichTextValue
/**
* Previous value.
*/
previousValue: RichTextValue
/**
* Source of the change.
*/
source: 'user' | 'api' | 'silent'
}
ToolbarConfigRich text editor toolbar layout (named preset with grouped format buttons).
interface ToolbarConfig {
/**
* Toolbar name/key.
*/
name: string
/**
* Toolbar groups - each group is an array of format buttons.
*/
groups: ToolbarGroup[]
}
EditorEventEditor event types.
type EditorEvent = 'text-change' | 'selection-change' | 'focus' | 'blur'
EditorEventHandlerEvent handler for editor events.
type EditorEventHandler<T = unknown> = (data: T) => void
FormatTypeEditor format types.
type FormatType =
| 'bold'
| 'italic'
| 'underline'
| 'strike'
| 'link'
| 'image'
| 'video'
| 'blockquote'
| 'code-block'
| 'header'
| 'list'
| 'indent'
| 'align'
| 'color'
| 'background'
| 'font'
| 'size'
| 'script'
| 'direction'
| 'clean'
ToolbarGroupA group of format buttons displayed together in the toolbar (e.g. [bold, italic, underline]).
type ToolbarGroup = (FormatType | FormatButton)[]
createEditor(options)Create a new rich text editor instance using the current provider.
function createEditor(options: EditorOptions): RichTextEditor
options — Editor configuration (container, toolbar, initial value, etc.).Returns: A RichTextEditor instance for controlling the editor.
createEmptyValue()Create an empty rich text value suitable for initializing an editor.
function createEmptyValue(): RichTextValue
Returns: An empty RichTextValue in the provider's internal format.
createSimpleRichTextProvider()Create a simple contentEditable-based rich text provider. This is a basic
fallback — for production use, prefer a dedicated provider like
@molecule/app-rich-text-quill.
function createSimpleRichTextProvider(): RichTextProvider
Returns: A RichTextProvider using the browser's contentEditable API.
getProvider()Get the current rich text provider. Falls back to a simple contentEditable-based provider if none has been explicitly set.
function getProvider(): RichTextProvider
Returns: The active RichTextProvider instance.
hasProvider()Check if a rich text provider has been registered.
function hasProvider(): boolean
Returns: Whether a RichTextProvider has been bonded.
htmlToValue(html)Convert an HTML string to the provider's internal rich text format.
function htmlToValue(html: string): RichTextValue
html — The HTML string to convert.Returns: A RichTextValue representing the HTML content.
setProvider(provider)Set the rich text provider.
function setProvider(provider: RichTextProvider): void
provider — RichTextProvider implementation to register.textToValue(text)Convert a plain text string to the provider's internal rich text format.
function textToValue(text: string): RichTextValue
text — The plain text string to convert.Returns: A RichTextValue representing the text content.
defaultToolbarsDefault toolbar presets.
const defaultToolbars: Record<string, ToolbarConfig>
Peer dependencies:
@molecule/app-bond ^1.0.1@molecule/app-bond
dompurify
Toolbar presets are 'minimal' | 'standard' | 'full' (see
defaultToolbars). There is no 'basic' preset — the quill bond
silently substitutes standard for unknown names.
If you never call setProvider(), the first editor call silently
self-bonds a minimal contentEditable fallback: NO toolbar UI, no delta
support, basic formatting only. Fine for plain notes; wire the quill
bond for real editing. hasProvider() reports whether a provider was
explicitly bonded before this fallback kicks in.
The fallback sanitizes all HTML through DOMPurify (bundled). Other providers own their own sanitization — always treat stored HTML as untrusted when rendering outside the editor.
Browser-only: createEditor touches document/window — do not call
during SSR.