Vue 3 components and composables for building rich text editors with tiptap
—
Core editor functionality with Vue 3 reactive state integration for building rich text editors.
The Vue 3-specific editor class that extends the core tiptap editor with reactive state management.
/**
* Vue 3 editor class with reactive state management
* Extends the core tiptap editor with Vue-specific features
*/
class Editor extends CoreEditor {
constructor(options?: Partial<EditorOptions>);
/** Get the current reactive editor state */
get state(): EditorState;
/** Get the reactive extension storage */
get storage(): Storage;
/** Vue content component reference */
contentComponent: ContentComponent | null;
/** Vue app context for provide/inject */
appContext: AppContext | null;
/**
* Register a ProseMirror plugin with reactive state updates
* @param plugin - The plugin to register
* @param handlePlugins - Optional plugin handling function
* @returns Updated editor state
*/
registerPlugin(
plugin: Plugin,
handlePlugins?: (newPlugin: Plugin, plugins: Plugin[]) => Plugin[]
): EditorState;
/**
* Unregister a ProseMirror plugin with reactive state updates
* @param nameOrPluginKey - Plugin name or key to unregister
* @returns Updated editor state or undefined
*/
unregisterPlugin(nameOrPluginKey: string | PluginKey): EditorState | undefined;
}
interface ContentComponent {
ctx: ComponentPublicInstance;
}Key Features:
Usage Examples:
import { Editor } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";
// Create editor instance
const editor = new Editor({
content: '<p>Hello World!</p>',
extensions: [StarterKit],
onUpdate: ({ editor }) => {
console.log('Content updated:', editor.getHTML());
},
});
// Access reactive state
console.log(editor.state.doc.textContent);
// Register plugins dynamically
import { Plugin } from "@tiptap/pm/state";
const customPlugin = new Plugin({
key: new PluginKey('custom'),
// plugin implementation
});
editor.registerPlugin(customPlugin);Vue 3 composition API hook for creating and managing editor instances with automatic lifecycle management.
/**
* Vue 3 composable for creating and managing editor instances
* Handles mounting, unmounting, and cleanup automatically
* @param options - Editor configuration options
* @returns Reactive reference to editor instance
*/
function useEditor(options?: Partial<EditorOptions>): Ref<Editor | undefined>;Lifecycle Management:
Usage Examples:
<template>
<div v-if="editor">
<EditorContent :editor="editor" />
</div>
</template>
<script setup>
import { useEditor, EditorContent } from "@tiptap/vue-3";
import StarterKit from "@tiptap/starter-kit";
// Basic usage
const editor = useEditor({
content: '<p>Initial content</p>',
extensions: [StarterKit],
});
// With reactive options
import { ref, watch } from 'vue';
const content = ref('<p>Dynamic content</p>');
const editable = ref(true);
const editor = useEditor({
content: content.value,
editable: editable.value,
extensions: [StarterKit],
onUpdate: ({ editor }) => {
content.value = editor.getHTML();
},
});
// Watch for option changes
watch([content, editable], ([newContent, newEditable]) => {
if (editor.value) {
editor.value.commands.setContent(newContent);
editor.value.setEditable(newEditable);
}
});
</script>interface EditorOptions {
/** Initial content as HTML string, JSON object, or Node */
content?: Content;
/** Array of extensions to use */
extensions?: Extensions;
/** Whether the editor is editable */
editable?: boolean;
/** Auto-focus behavior */
autofocus?: FocusPosition | boolean;
/** Enable input rules */
enableInputRules?: boolean;
/** Enable paste rules */
enablePasteRules?: boolean;
/** Enable content parse */
enableContentCheck?: boolean;
/** Event callbacks */
onCreate?: (props: EditorEvents['create']) => void;
onUpdate?: (props: EditorEvents['update']) => void;
onSelectionUpdate?: (props: EditorEvents['selectionUpdate']) => void;
onTransaction?: (props: EditorEvents['transaction']) => void;
onFocus?: (props: EditorEvents['focus']) => void;
onBlur?: (props: EditorEvents['blur']) => void;
onDestroy?: () => void;
/** DOM element to mount to */
element?: Element;
/** Enable drop cursor */
enableDropCursor?: boolean;
/** Enable gap cursor */
enableGapCursor?: boolean;
/** Injectable items for dependency injection */
injectCSS?: boolean;
/** Transform pasted content */
transformPastedText?: (text: string) => string;
transformPastedHTML?: (html: string) => string;
transformClipboardText?: (text: string) => string;
}
type Content = string | JSONContent | HTMLContent | null;
type Extensions = Extension[];
type FocusPosition = 'start' | 'end' | 'all' | number | boolean | null;Install with Tessl CLI
npx tessl i tessl/npm-tiptap--vue-3