@trevixal/vue

Vue 3 bindings for the Trevixal editor: useEditor composable, EditorContent component, shallow-ref snapshot.
628 4
Install
npm install @trevixal/vue
Latest Version:1.1.0
Vue:3
License:Apache-2.0
Last Updated:Oct 22, 2026
Links: GitHub  ·  npm
Maintainer: adityabhalsod

@trevixal/vue

CI npm types license

Documentation · Live editor · Changelog · Issues

The Trevixal editor

Features

  • useEditor composable and an EditorContent component
  • Shallow-ref snapshots, so a keystroke re-renders only what changed
  • Vue components inside the document as node views
  • 0.8 kB minified and gzipped, with TypeScript types in the package

Vue 3 bindings for the Trevixal editor.

npm install @trevixal/core @trevixal/vue

Usage

<script setup>
import { Schema, defaultNodes, defaultMarks } from '@trevixal/core'
import { useEditor, useEditorSnapshot, EditorContent } from '@trevixal/vue'

const editor = useEditor({
  schema: new Schema({ nodes: defaultNodes(), marks: defaultMarks() }),
})
const snapshot = useEditorSnapshot(editor)
</script>

<template>
  <div class="trevixal">
    <button
      :aria-pressed="snapshot?.activeMarks.includes('bold')"
      @click="editor?.commands.toggleMark('bold')"
    >Bold</button>
    <EditorContent :editor="editor" placeholder="Write something…" />
  </div>
</template>

useEditor creates the editor on mount and destroys it on unmount. useEditorSnapshot is a shallow ref that changes only when the toolbar state does, typing does not touch it, because the editor's DOM lives outside Vue's reactivity (ADR-0007).

Vue components inside the document

<EditorContent :editor="editor" :node-views="{ counter: Counter }" />

A node view receives { node, editor, updateAttrs } and is rendered into a container the editor owns, with Vue's render, not a second createApp, so it shares your application's context and is torn down with the node.

<script setup>
const props = defineProps(['node', 'editor', 'updateAttrs'])
</script>

<template>
  <button @click="updateAttrs({ count: Number(node.attrs.count) + 1 })">
    count: {{ node.attrs.count }}
  </button>
</template>

The node arrives by value and the component is redrawn on every change rather than handed a reactive proxy: the document is immutable, so a new node is the change, and a proxy would invite writing to a node that no longer exists. Hold no state in a node view, read it from node, write it with updateAttrs, and undo will rewind your component along with everything else.

Server rendering

Importing this package touches no DOM, and useEditor creates nothing until the component mounts, so it is safe in an SSR build. There is a test that imports it with no DOM present and checks its public symbols are there.

License

Apache-2.0

Related Packages

@domternal/vue

MIT-licensed Vue 3 components for the Domternal rich text editor

11,840 232
@hebamuh28/mini-editor

A lightweight rich text editor component for Vue 3

1,383
@abhinavakhil/penna-vue

Vue 3 bindings for @abhinavakhil/penna-core

307 0
@tessera-editor/vue

Tessera Vue 3 binding with the full default UI

235 0
@oh-new-editor/vue

Vue adapter for Oh New Editor

165 0

Version History

Version Released Vue License
1.1.0 >=3.4.0 Apache-2.0
1.0.5 >=3.4.0 Apache-2.0
1.0.4 >=3.4.0 Apache-2.0
1.0.3 >=3.4.0 Apache-2.0
1.0.2 >=3.4.0 Apache-2.0