Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

@labbs/openblock-react

React bindings for the OpenBlock rich text editor.

Installation

npm install @labbs/openblock-react @labbs/openblock-core
# or
pnpm add @labbs/openblock-react @labbs/openblock-core

Quick Start

import { useOpenBlock, OpenBlockView, SlashMenu, BubbleMenu } from '@labbs/openblock-react';
import '@labbs/openblock-core/styles/editor.css';

function MyEditor() {
  const editor = useOpenBlock({
    initialContent: [
      {
        type: 'heading',
        props: { level: 1 },
        content: [{ type: 'text', text: 'Hello World', styles: {} }],
      },
      {
        type: 'paragraph',
        content: [{ type: 'text', text: 'Start editing...', styles: {} }],
      },
    ],
  });

  if (!editor) return <div>Loading...</div>;

  return (
    <div className="editor-container">
      <OpenBlockView editor={editor} />
      <SlashMenu editor={editor} />
      <BubbleMenu editor={editor} />
    </div>
  );
}

Hooks

useOpenBlock

Creates and manages an OpenBlockEditor instance.

const editor = useOpenBlock({
  initialContent: [...],
  editable: true,
  autoFocus: 'end',
  onUpdate: (blocks) => console.log(blocks),
  deps: [someValue], // Recreate editor when deps change
});

useEditorContent

Subscribe to document changes.

const blocks = useEditorContent(editor);
// blocks updates whenever the document changes

useEditorSelection

Subscribe to selection changes.

const selectedBlocks = useEditorSelection(editor);
// selectedBlocks updates when selection changes

useEditorFocus

Track editor focus state.

const isFocused = useEditorFocus(editor);

Components

OpenBlockView

Renders the editor view.

<OpenBlockView
  editor={editor}
  className="my-editor"
/>

With ref for imperative access:

const viewRef = useRef<OpenBlockViewRef>(null);

<OpenBlockView
  ref={viewRef}
  editor={editor}
/>

// Later: viewRef.current?.focus()

SlashMenu

Command palette triggered by typing /.

<SlashMenu editor={editor} />

See SlashMenu Customization for advanced usage.

BubbleMenu

Floating toolbar for text formatting.

<BubbleMenu editor={editor} />

See BubbleMenu Customization for advanced usage.

ColorPicker

Color picker for text and background colors.

import { ColorPicker } from '@labbs/openblock-react';

<ColorPicker
  editor={editor}
  currentTextColor={textColor}
  currentBackgroundColor={bgColor}
/>

See ColorPicker Customization for advanced usage.

TableHandles

Row/column manipulation handles for tables.

<TableHandles editor={editor} />

MediaMenu

Menu for media blocks (images, videos, files).

<MediaMenu editor={editor} />

Customization API

BubbleMenu Customization

The BubbleMenu supports extensive customization through props.

Props

interface BubbleMenuProps {
  editor: OpenBlockEditor | null;
  customItems?: BubbleMenuItem[];  // Add custom buttons
  itemOrder?: string[];            // Control order (use '---' for dividers)
  hideItems?: string[];            // Hide default items
  className?: string;
  children?: React.ReactNode;
}

Default Item IDs

  • Block type: blockType
  • Alignment: alignLeft, alignCenter, alignRight
  • Formatting: bold, italic, underline, strikethrough
  • Style: code, link, color

Example: Add a Custom Button

import { BubbleMenu, BubbleMenuItem } from '@labbs/openblock-react';

const translateButton: BubbleMenuItem = {
  id: 'translate',
  label: 'Translate',
  icon: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <path d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10" />
    </svg>
  ),
  action: async (editor, state) => {
    const text = editor.pm.state.doc.textBetween(state.from, state.to);
    const translated = await translateAPI(text);
    // Replace selection...
  },
};

<BubbleMenu
  editor={editor}
  customItems={[translateButton]}
/>

Example: Reorder Items

<BubbleMenu
  editor={editor}
  itemOrder={[
    'bold', 'italic', 'underline',
    '---',  // Divider
    'link', 'color',
    '---',
    'translate',  // Custom item
  ]}
/>

Example: Minimal Toolbar

<BubbleMenu
  editor={editor}
  itemOrder={['bold', 'italic', '---', 'link']}
/>

Example: Hide Items

<BubbleMenu
  editor={editor}
  hideItems={['strikethrough', 'code', 'alignLeft', 'alignCenter', 'alignRight']}
/>

SlashMenu Customization

The SlashMenu supports customization similar to BubbleMenu.

Props

interface SlashMenuProps {
  editor: OpenBlockEditor | null;
  items?: SlashMenuItem[];         // Replace all defaults
  customItems?: SlashMenuItem[];   // Add to defaults
  itemOrder?: string[];            // Control order (only listed items shown)
  hideItems?: string[];            // Hide specific items
  renderItem?: (item: SlashMenuItem, isSelected: boolean) => React.ReactNode;
  className?: string;
}

Default Item IDs

  • Text: paragraph, heading
  • Lists: bulletList, numberedList, checkList
  • Blocks: blockquote, codeBlock, callout, divider
  • Tables: table
  • Media: image, video, audio, file

Example: Add Custom Items

import { SlashMenu, SlashMenuItem } from '@labbs/openblock-react';

const customItems: SlashMenuItem[] = [
  {
    id: 'emoji',
    title: 'Emoji',
    description: 'Insert an emoji picker',
    icon: '😀',
    action: (editor) => {
      // Show emoji picker...
    },
  },
  {
    id: 'template',
    title: 'Template',
    description: 'Insert a predefined template',
    icon: '📄',
    action: (editor) => {
      // Insert template...
    },
  },
];

<SlashMenu
  editor={editor}
  customItems={customItems}
/>

Example: Custom Order

<SlashMenu
  editor={editor}
  itemOrder={['paragraph', 'heading', 'bulletList', 'emoji', 'template']}
/>

Example: Hide Items

<SlashMenu
  editor={editor}
  hideItems={['table', 'video', 'audio', 'file']}
/>

ColorPicker Customization

The ColorPicker component allows custom color palettes.

Props

interface ColorPickerProps {
  editor: OpenBlockEditor;
  currentTextColor: string | null;
  currentBackgroundColor: string | null;
  textColors?: ColorOption[];       // Custom text color palette
  backgroundColors?: ColorOption[]; // Custom background color palette
  textColorLabel?: string;          // Label for text color section
  backgroundColorLabel?: string;    // Label for background section
  onClose?: () => void;
}

interface ColorOption {
  value: string;  // CSS color value ('' for default/remove)
  label: string;  // Display label
}

Default Palettes

import { DEFAULT_TEXT_COLORS, DEFAULT_BACKGROUND_COLORS } from '@labbs/openblock-react';

// DEFAULT_TEXT_COLORS includes:
// Default, Gray, Red, Orange, Yellow, Green, Blue, Purple, Pink

// DEFAULT_BACKGROUND_COLORS includes:
// Default, Gray, Red, Orange, Yellow, Green, Blue, Purple, Pink (lighter versions)

Example: Brand Color Palette

import { ColorPicker, ColorOption } from '@labbs/openblock-react';

const brandTextColors: ColorOption[] = [
  { value: '', label: 'Default' },
  { value: '#1a1a1a', label: 'Black' },
  { value: '#0066cc', label: 'Primary' },
  { value: '#00994d', label: 'Success' },
  { value: '#cc3300', label: 'Error' },
];

const brandBackgroundColors: ColorOption[] = [
  { value: '', label: 'None' },
  { value: '#e6f2ff', label: 'Blue' },
  { value: '#e6ffe6', label: 'Green' },
  { value: '#ffe6e6', label: 'Red' },
];

<ColorPicker
  editor={editor}
  currentTextColor={textColor}
  currentBackgroundColor={bgColor}
  textColors={brandTextColors}
  backgroundColors={brandBackgroundColors}
  textColorLabel="Text Color"
  backgroundColorLabel="Highlight"
/>

Accessing ProseMirror

The editor instance provides full ProseMirror access:

function MyEditor() {
  const editor = useOpenBlock({...});

  const handleBold = () => {
    editor.toggleBold();
  };

  const handleCustomAction = () => {
    // Direct ProseMirror access
    const tr = editor.pm.createTransaction();
    tr.insertText('Custom text');
    editor.pm.dispatch(tr);
  };

  return (
    <>
      <button onClick={handleBold}>Bold</button>
      <button onClick={handleCustomAction}>Insert</button>
      <OpenBlockView editor={editor} />
    </>
  );
}

Exports

Components

  • OpenBlockView - Main editor view
  • SlashMenu - Command palette
  • BubbleMenu - Floating toolbar
  • ColorPicker - Color selection
  • TableMenu - Table manipulation menu
  • TableHandles - Table row/column handles
  • MediaMenu - Media block menu
  • LinkPopover - Link editing popover

Hooks

  • useOpenBlock - Create editor instance
  • useEditorContent - Subscribe to content
  • useEditorSelection - Subscribe to selection
  • useEditorFocus - Track focus state

Constants

  • BUBBLE_MENU_ITEMS - Default bubble menu items map
  • DEFAULT_BUBBLE_MENU_ORDER - Default bubble menu item order
  • DEFAULT_TEXT_COLORS - Default text color palette
  • DEFAULT_BACKGROUND_COLORS - Default background color palette

Types

  • OpenBlockViewProps, OpenBlockViewRef
  • SlashMenuProps, SlashMenuItem
  • BubbleMenuProps, BubbleMenuItem
  • ColorPickerProps, ColorOption
  • TableMenuProps, TableHandlesProps
  • MediaMenuProps, LinkPopoverProps

Documentation

For complete documentation, see:

License

Apache-2.0