Skip to main content

Editor View React API

The Editor View React API provides React components and hooks for integrating the Barocss Editor into React applications.

EditorView Component

The main React component that renders the editor with layered content, decorators, selection, and custom overlays.

Props

interface EditorViewProps {
editor: Editor; // Editor core instance
options?: EditorViewOptions; // View configuration
children?: ReactNode; // Additional children rendered inside the view
}

Options:

interface EditorViewOptions {
registry?: RendererRegistry; // Renderer registry (defaults to global)
className?: string; // CSS class for the root element
layers?: EditorViewLayersConfig; // Per-layer configuration
}

Layers Config:

interface EditorViewLayersConfig {
content?: EditorViewContentLayerOptions; // Content layer options
decorator?: { className?: string }; // Decorator overlay layer
selection?: { className?: string }; // Selection highlight layer
context?: { className?: string }; // Context menu / tooltip layer
custom?: { className?: string }; // Custom overlay layer
}

Ref

type EditorViewRef = EditorViewHandle;

Access the imperative API through a React ref:

import { useRef } from 'react';
import { EditorView, EditorViewRef } from '@barocss/editor-view-react';

function MyEditor({ editor }: { editor: Editor }) {
const viewRef = useRef<EditorViewRef>(null);

return <EditorView ref={viewRef} editor={editor} />;
}

Example

import { EditorView } from '@barocss/editor-view-react';
import { Editor } from '@barocss/editor-core';
import { getGlobalRegistry } from '@barocss/dsl';

function App() {
const editor = useEditor(); // your editor instance

return (
<EditorView
editor={editor}
options={{
registry: getGlobalRegistry(),
className: 'my-editor',
layers: {
content: { editable: true, className: 'content' },
decorator: { className: 'decorators' },
selection: { className: 'selection' }
}
}}
/>
);
}

EditorViewHandle (Ref API)

The imperative handle exposed through EditorView's ref. Provides decorator management, selection conversion, and DOM access.

Decorator Management

addDecorator(decorator): void

Adds a decorator or decorator generator to the view.

Parameters:

  • decorator: Decorator | DecoratorGenerator - Decorator instance or generator function

Example:

viewRef.current.addDecorator({
sid: 'highlight-1',
stype: 'highlight',
category: 'inline',
target: { sid: 'text-1', startOffset: 0, endOffset: 10 }
});

removeDecorator(id): void

Removes a decorator by its ID.

Parameters:

  • id: string - Decorator sid to remove

Example:

viewRef.current.removeDecorator('highlight-1');

updateDecorator(id, updates): void

Updates properties of an existing decorator.

Parameters:

  • id: string - Decorator sid to update
  • updates: Partial<Decorator> - Partial decorator properties to merge

Example:

viewRef.current.updateDecorator('highlight-1', {
target: { sid: 'text-1', startOffset: 2, endOffset: 8 }
});

getDecorators(options?): Decorator[]

Retrieves decorators matching optional query criteria.

Parameters:

  • options?: DecoratorQueryOptions - Optional filter criteria

Returns:

  • Decorator[] - Array of matching decorators

Example:

const inlineDecorators = viewRef.current.getDecorators({
category: 'inline'
});

getDecorator(id): Decorator | undefined

Gets a single decorator by ID.

Parameters:

  • id: string - Decorator sid

Returns:

  • Decorator | undefined - Decorator instance or undefined

Example:

const decorator = viewRef.current.getDecorator('highlight-1');
if (decorator) {
console.log('Found:', decorator.stype);
}

exportDecorators(): DecoratorExportData

Exports all decorators as serializable data.

Returns:

  • DecoratorExportData - Serializable decorator state

Example:

const exported = viewRef.current.exportDecorators();
localStorage.setItem('decorators', JSON.stringify(exported));

loadDecorators(data, patternFunctions?): void

Loads decorators from exported data.

Parameters:

  • data: DecoratorExportData - Previously exported decorator data
  • patternFunctions?: Record<string, Function> - Optional pattern function map for pattern decorators

Example:

const saved = JSON.parse(localStorage.getItem('decorators') || '{}');
viewRef.current.loadDecorators(saved);

defineDecoratorType(type, category, schema): void

Defines a new decorator type at runtime.

Parameters:

  • type: string - Decorator type name
  • category: 'inline' | 'block' | 'layer' - Decorator category
  • schema: object - Decorator schema definition

Example:

viewRef.current.defineDecoratorType('comment', 'inline', {
attrs: { author: 'string', text: 'string' }
});

DOM & Selection

contentEditableElement: HTMLElement | null

The contentEditable DOM element managed by the view. Returns null if the view is not mounted.

Example:

const el = viewRef.current.contentEditableElement;
if (el) {
el.focus();
}

convertModelSelectionToDOM(sel): void

Converts a model selection to a DOM selection and applies it to the document.

Parameters:

  • sel: ModelSelection - Model selection to apply

Example:

viewRef.current.convertModelSelectionToDOM({
type: 'range',
startNodeId: 'text-1',
startOffset: 0,
endNodeId: 'text-1',
endOffset: 5
});

convertDOMSelectionToModel(selection): ModelSelection

Converts a native DOM Selection to a model selection.

Parameters:

  • selection: Selection - Native DOM Selection object

Returns:

  • ModelSelection - Equivalent model selection

Example:

const domSelection = window.getSelection()!;
const modelSel = viewRef.current.convertDOMSelectionToModel(domSelection);

convertStaticRangeToModel(staticRange): ModelSelection | null

Converts a StaticRange to a model selection.

Parameters:

  • staticRange: StaticRange - Native StaticRange object

Returns:

  • ModelSelection | null - Equivalent model selection, or null if conversion fails

Example:

const modelSel = viewRef.current.convertStaticRangeToModel(staticRange);
if (modelSel) {
console.log('Converted:', modelSel);
}

EditorViewContentLayer Component

Renders the editable content layer within an EditorView.

Props

interface EditorViewContentLayerProps {
options?: EditorViewContentLayerOptions;
}

Options:

interface EditorViewContentLayerOptions {
registry?: RendererRegistry; // Override renderer registry
className?: string; // CSS class for the content layer
editable?: boolean; // Enable contentEditable (default: true)
}

Example:

import { EditorView, EditorViewContentLayer } from '@barocss/editor-view-react';

function CustomEditor({ editor }: { editor: Editor }) {
return (
<EditorView editor={editor}>
<EditorViewContentLayer
options={{
className: 'custom-content',
editable: true
}}
/>
</EditorView>
);
}

EditorViewLayer Component

Renders a named overlay layer (decorator, selection, context, or custom) within an EditorView.

Props

interface EditorViewLayerProps {
layer: EditorViewLayerType; // Layer type
className?: string; // CSS class for the layer
style?: React.CSSProperties; // Inline styles
children?: ReactNode; // Additional children
}

Layer Types:

type EditorViewLayerType = 'decorator' | 'selection' | 'context' | 'custom';

Example:

import { EditorView, EditorViewContentLayer, EditorViewLayer } from '@barocss/editor-view-react';

function FullEditor({ editor }: { editor: Editor }) {
return (
<EditorView editor={editor}>
<EditorViewContentLayer />
<EditorViewLayer layer="decorator" className="decorator-overlay" />
<EditorViewLayer layer="selection" className="selection-overlay" />
<EditorViewLayer layer="custom" className="custom-overlay">
<MyCustomToolbar />
</EditorViewLayer>
</EditorView>
);
}

Context Hooks

EditorViewContextProvider

Provides editor view context to descendant components.

function EditorViewContextProvider({
editor,
children
}: {
editor: Editor;
children: ReactNode;
}): JSX.Element

Example:

import { EditorViewContextProvider } from '@barocss/editor-view-react';

function App({ editor }: { editor: Editor }) {
return (
<EditorViewContextProvider editor={editor}>
<Toolbar />
<EditorView editor={editor} />
</EditorViewContextProvider>
);
}

useEditorViewContext

Returns the current editor view context. Throws if used outside a provider.

function useEditorViewContext(): EditorViewContextValue

Returns:

  • EditorViewContextValue - Context value containing the editor instance and view utilities

Example:

import { useEditorViewContext } from '@barocss/editor-view-react';

function Toolbar() {
const { editor } = useEditorViewContext();

return (
<button onClick={() => editor.commands.execute('toggleBold')}>
Bold
</button>
);
}

useOptionalEditorViewContext

Returns the current editor view context, or null if outside a provider. Safe for components that may render with or without an editor.

function useOptionalEditorViewContext(): EditorViewContextValue | null

Returns:

  • EditorViewContextValue | null - Context value or null

Example:

import { useOptionalEditorViewContext } from '@barocss/editor-view-react';

function StatusBar() {
const ctx = useOptionalEditorViewContext();

if (!ctx) {
return <span>No editor</span>;
}

return <span>Editor active</span>;
}

ModelSelection Type

Represents selection state in the model layer.

type ModelSelection =
| { type: 'none' }
| {
type: 'range';
startNodeId: string;
startOffset: number;
endNodeId: string;
endOffset: number;
direction?: 'forward' | 'backward';
}
| { type: 'node'; nodeId: string };

Variants:

  • none — No active selection
  • range — Text range selection with start/end positions and optional direction
  • node — Entire node selected (e.g., an image or embed)

Example:

const collapsed: ModelSelection = {
type: 'range',
startNodeId: 'text-1',
startOffset: 5,
endNodeId: 'text-1',
endOffset: 5
};

const expanded: ModelSelection = {
type: 'range',
startNodeId: 'text-1',
startOffset: 0,
endNodeId: 'text-2',
endOffset: 10,
direction: 'forward'
};

const nodeSelection: ModelSelection = {
type: 'node',
nodeId: 'image-1'
};

Complete Example

import { useRef } from 'react';
import { EditorView, EditorViewRef, EditorViewContentLayer, EditorViewLayer } from '@barocss/editor-view-react';
import { Editor } from '@barocss/editor-core';
import { getGlobalRegistry } from '@barocss/dsl';

function MyEditor({ editor }: { editor: Editor }) {
const viewRef = useRef<EditorViewRef>(null);

const addHighlight = () => {
viewRef.current?.addDecorator({
sid: `hl-${Date.now()}`,
stype: 'highlight',
category: 'inline',
target: { sid: 'text-1', startOffset: 0, endOffset: 5 }
});
};

const getSelection = () => {
const domSel = window.getSelection();
if (domSel && viewRef.current) {
const modelSel = viewRef.current.convertDOMSelectionToModel(domSel);
console.log('Model selection:', modelSel);
}
};

return (
<div>
<div className="toolbar">
<button onClick={addHighlight}>Add Highlight</button>
<button onClick={getSelection}>Log Selection</button>
</div>
<EditorView
ref={viewRef}
editor={editor}
options={{
registry: getGlobalRegistry(),
className: 'editor-root',
layers: {
content: { editable: true },
decorator: { className: 'decorator-layer' },
selection: { className: 'selection-layer' }
}
}}
>
<EditorViewContentLayer />
<EditorViewLayer layer="decorator" />
<EditorViewLayer layer="selection" />
<EditorViewLayer layer="custom">
<FloatingToolbar />
</EditorViewLayer>
</EditorView>
</div>
);
}