Skip to content

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-model or model-value plus update: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:

vue
<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.

ts
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 areaDocumentation
Controlled HTML, reactive config, disabled/readonly, methodsBasic and reactive usage, API reference
Menubar, toolbar overflow, history, clipboard, shortcuts, status, resize, printMenubar customization, Workflow and responsive UI
Headings, fonts, colors, line height, case, lists, indentationText formatting, Lists and indentation
Links, anchors, video, audio, iframe, and tablesLinks and anchors, Media and embeds, Table editor
Mentions, merge tags, and consumer-defined templatesMentions, Merge tags, Templates
File/URL/paste image uploads, alignment, resize, and deletionImage uploads
Emoji, symbols, horizontal rules, and date-timeSpecial characters and emoji, Horizontal rules and date-time
Source HTML, preview, fullscreen, find, and replaceCode, preview, and fullscreen, Find and replace
Sanitization, scoped CSS, public types, and Laravel integrationSecurity, 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.

Released under the MIT License. Copyright © Er Amit Gupta