-
-
Notifications
You must be signed in to change notification settings - Fork 0
Component API Reference
This document provides a comprehensive API reference for all React components, context providers, hooks, and utilities exported by vats.
The top-level container that sets up the Jotai state store and tunnel context for an editor instance. Every editor must be wrapped in an EditorRoot.
import { EditorRoot, type EditorRootProps } from "@vats-editor/core";| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
Required | Editor child components (EditorContent, toolbars, etc.) |
store |
ReturnType<typeof createStore> |
undefined |
Optional custom Jotai store instance. If omitted, EditorRoot creates an isolated store instance automatically. |
<EditorRoot>
<EditorContent extensions={extensions} />
</EditorRoot>The core rendering container for the Tiptap editor view. It wraps Tiptap's EditorProvider and binds the active Jotai store to the editor instance.
import { EditorContent, type EditorContentProps } from "@vats-editor/core";EditorContentProps extends Omit<EditorProviderProps, "content"> and accepts:
| Prop | Type | Default | Description |
|---|---|---|---|
initialContent |
JSONContent |
undefined |
Initial document content represented as a ProseMirror JSON tree |
extensions |
AnyExtension[] |
[] |
Array of configured Tiptap extensions and plugins |
className |
string |
undefined |
CSS class names applied to the outer wrapper div
|
editorProps |
EditorProps |
{} |
ProseMirror editor view properties (DOM event handlers, HTML attributes) |
onUpdate |
(props: { editor: EditorInstance }) => void |
undefined |
Callback fired whenever document content changes |
onCreate |
(props: { editor: EditorInstance }) => void |
undefined |
Callback fired when the editor view is initialized |
onBeforeCreate |
(props: { editor: EditorInstance }) => void |
undefined |
Callback fired immediately prior to editor instantiation |
onDestroy |
() => void |
undefined |
Callback fired when the editor view is destroyed |
editable |
boolean |
true |
Controls whether the editor content is editable |
autofocus |
FocusPosition |
false |
Focus position on initial mount ("start", "end", "all", or boolean) |
slotBefore |
ReactNode |
undefined |
Node rendered immediately before the editor DOM element |
slotAfter |
ReactNode |
undefined |
Node rendered immediately after the editor DOM element (e.g., <ImageResizer />) |
children |
ReactNode |
undefined |
Child elements, such as <EditorBubble> and <EditorCommand>
|
<EditorContent
initialContent={myDocumentJson}
extensions={defaultExtensions}
className="prose-container"
editorProps={{
handleDOMEvents: {
keydown: (_view, event) => handleCommandNavigation(event),
},
attributes: {
class: "prose dark:prose-invert focus:outline-none",
},
}}
onUpdate={({ editor }) => console.log(editor.getJSON())}
slotAfter={<ImageResizer />}
>
<EditorBubble>{/* Bubble menu content */}</EditorBubble>
<EditorCommand>{/* Slash command content */}</EditorCommand>
</EditorContent>A floating bubble menu rendered above selected text. It automatically handles positioning, visibility rules, and node selection checks.
import { EditorBubble, type EditorBubbleProps } from "@vats-editor/core";| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
Required | Formatting buttons, selectors, and controls |
className |
string |
undefined |
CSS class names for the floating menu container |
options |
BubbleMenuOptions |
undefined |
Tippy.js positioning and animation options |
shouldShow |
(props: { editor: Editor; state: EditorState }) => boolean |
Default function | Custom visibility predicate. By default, hidden if selection is empty, editor is non-editable, or node is an image. |
<EditorBubble className="flex gap-1 rounded-md border bg-background p-1 shadow-md">
<button onClick={() => editor.chain().focus().toggleBold().run()}>Bold</button>
<button onClick={() => editor.chain().focus().toggleItalic().run()}>Italic</button>
</EditorBubble>A convenience wrapper for items inside the bubble menu.
import { EditorBubbleItem } from "@vats-editor/core";| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
Required | Button or content element |
asChild |
boolean |
false |
If true, merges props onto the immediate child element |
onSelect |
(editor: EditorInstance) => void |
undefined |
Click handler receiving the active editor instance |
Container for the slash command popup menu. It renders via React Tunnel to position itself at the user's cursor when / is typed.
import {
EditorCommand,
EditorCommandList,
EditorCommandItem,
EditorCommandEmpty,
} from "@vats-editor/core";-
EditorCommand: Root command popup container based oncmdk. -
EditorCommandEmpty: Message shown when no suggestions match the user query. -
EditorCommandList: Container list for command suggestion rows. -
EditorCommandItem: Individual selectable suggestion item.
| Prop | Type | Description |
|---|---|---|
value |
string |
Unique search key and label for the item |
onCommand |
(props: { editor: EditorInstance; range: Range }) => void |
Action executed when the item is chosen (Enter key or click) |
className |
string |
CSS class names for item styling |
children |
ReactNode |
Item layout (icons, title, description) |
<EditorCommand className="z-50 max-h-72 overflow-y-auto rounded-md border bg-background p-1 shadow-lg">
<EditorCommandEmpty className="p-2 text-sm text-muted-foreground">
No results
</EditorCommandEmpty>
<EditorCommandList>
<EditorCommandItem
value="Heading 2"
onCommand={({ editor, range }) => {
editor.chain().focus().deleteRange(range).setHeading({ level: 2 }).run();
}}
className="flex items-center gap-2 rounded px-2 py-1 text-sm hover:bg-accent"
>
<span className="font-medium">Heading 2</span>
</EditorCommandItem>
</EditorCommandList>
</EditorCommand>A React overlay component that renders interactive drag handles on currently selected image nodes. Place this inside slotAfter of EditorContent.
import { ImageResizer } from "@vats-editor/core";
<EditorContent slotAfter={<ImageResizer />} />Retrieves the isolated Jotai store assigned to the nearest EditorRoot.
import { useEditorStore } from "@vats-editor/core";
const store = useEditorStore();The React Context object holding the Jotai store reference.
import { EditorStoreContext } from "@vats-editor/core";
import { useContext } from "react";
const store = useContext(EditorStoreContext);Re-exported from @tiptap/react to access the active editor instance inside child components.
import { useCurrentEditor } from "@tiptap/react";
function CustomButton() {
const { editor } = useCurrentEditor();
if (!editor) return null;
return (
<button onClick={() => editor.chain().focus().toggleStrike().run()}>
Strike
</button>
);
}-
handleCommandNavigation(event: KeyboardEvent): boolean: Dispatches synthetic keyboard events (ArrowUp,ArrowDown,Enter) to the command list, preventing default editor cursor movement while navigating slash commands.
-
getAllContent(editor: EditorInstance): string: Serializes the entire editor document into a clean Markdown string using the registered Markdown extension storage. -
isValidUrl(url: string): boolean: Validates whether a string is a well-formed HTTP/HTTPS URL. -
getUrlFromString(str: string): string | null: Extracts the first valid URL found within an arbitrary text string. -
getPrevText(editor: EditorInstance, position: number): string: Retrieves preceding text content before a specific cursor offset.
-
queryAtom: Holds the active slash command search filter string. -
rangeAtom: Holds the ProseMirror text range to replace when a slash command is executed. -
vatsStore/novelStore: Global fallback Jotai store instances.
Vats Editor is open source software released under the Apache-2.0 License.
GitHub | Issues | Discussions
-
Overview
-
Documentation
-
Architecture