Introduction
@erag/text-editor-vue is a dependency-free rich text editor component for Vue 3. The package uses Vue's Composition API and native browser editing APIs instead of wrapping another editor framework. Vue is its only peer dependency.
What it includes
- Controlled HTML content through
v-modelormodel-valueplusupdate:model-value. - Responsive menubar and toolbar controls for formatting, lists, links, media, tables, code, preview, and fullscreen.
- Optional mentions, merge tags, and consumer-provided templates.
- Consumer-controlled image upload and deletion callbacks, URL uploads with Fetch, paste uploads, alignment, and four-corner resizing.
- Source editing, sanitized preview, print, find and replace, special characters, emoji, and date/time insertion.
- Disabled and readonly modes, keyboard shortcuts, ARIA labels, selection preservation, and typed events.
- ESM output, generated TypeScript declarations, and package-scoped
erag-CSS.
How content flows
The editor is a controlled Vue component:
<script setup lang="ts">
import { shallowRef } from 'vue';
import { Editor } from '@erag/text-editor-vue';
import '@erag/text-editor-vue/style.css';
const content = shallowRef('<p>Hello</p>');
</script>
<template>
<Editor v-model="content" />
</template>Typing or running an editor action updates the generated HTML. The component emits update:modelValue only when that HTML changes. A new external model value updates the canvas without publishing the same value back in a loop.
Defaults and explicit configuration
Omitting init enables the full standard editor. Passing a partial object keeps defaults for omitted properties. Explicit toolbar and menubar choices are exact, and explicit plugin arrays filter plugin-backed controls instead of silently restoring excluded features.
import type { EditorInit } from '@erag/text-editor-vue';
const commentEditor: EditorInit = {
height: 240,
menubar: false,
statusbar: false,
plugins: ['history', 'formatting', 'lists', 'link'],
toolbar: 'bold italic | bullist numlist | link',
};Browser API limitations
Native contenteditable and editing commands have small browser differences. Clipboard operations require a user gesture and can be blocked by permissions. Fullscreen uses the Fullscreen API with a CSS fallback. Image uploads require a handler or URL supplied by your application.
The component is SSR-safe during initialization, but browser-only utilities cannot sanitize on the server. Always sanitize untrusted HTML again at your backend boundary.
Feature documentation map
| Package area | Documentation |
|---|---|
| Controlled HTML, reactive config, disabled/readonly, methods | Basic and reactive usage, API reference |
| Menubar, toolbar overflow, history, clipboard, shortcuts, status, resize, print | Menubar customization, Workflow and responsive UI |
| Headings, fonts, colors, line height, case, lists, indentation | Text formatting, Lists and indentation |
| Links, anchors, video, audio, iframe, and tables | Links and anchors, Media and embeds, Table editor |
| Mentions, merge tags, and consumer-defined templates | Mentions, Merge tags, Templates |
| File/URL/paste image uploads, alignment, resize, and deletion | Image uploads |
| Emoji, symbols, horizontal rules, and date-time | Special characters and emoji, Horizontal rules and date-time |
| Source HTML, preview, fullscreen, find, and replace | Code, preview, and fullscreen, Find and replace |
| Sanitization, scoped CSS, public types, and Laravel integration | Security, CSS customization, TypeScript types, Laravel and Inertia |
Next steps
Start with installation, continue to basic usage, and review the editor workflow and responsive UI. Use the configuration reference for the complete option list.