🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

fc-react-rich-editor

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fc-react-rich-editor

An advanced, open-source, 100% customizable rich text editor for React with full TypeScript support

latest
Source
npmnpm
Version
0.1.1
Version published
Weekly downloads
39
-80.79%
Maintainers
1
Weekly downloads
 
Created
Source

fc-react-rich-editor

A full-featured, customizable rich text editor for React with TypeScript support. Built on Slate.js.

Features

  • TypeScript-first – Full type safety and Slate module augmentation
  • Ready-to-use UI – Toolbar, hovering toolbar, right-click context menu (slash menu)
  • Blocks & formatting – Paragraphs, headings, blockquote, code block, bulleted/numbered lists, text alignment
  • Marks – Bold, italic, underline, strikethrough, inline code, font size, font color
  • Images – Insert by URL or upload (via callback), resize (drag corner), align left/center/right
  • Tables – Insert 2–6 columns, resizable columns, add/remove rows and columns, Tab navigation
  • Media – Links, variables ({{name}}), video embeds (YouTube, Vimeo, etc.)
  • Custom commands – Add your own context menu items (e.g. “Insert callout”) without writing a plugin
  • Plugins – Extend the Slate editor with custom behavior
  • Theming – CSS custom properties; override fonts, colors, radii
  • Serialization – HTML and Markdown serialize/deserialize
  • Headless – Use the useRichTextEditor hook for full control over rendering

Installation

npm install fc-react-rich-editor

Peer dependencies: React 18+ and React DOM.

Quick start

import { useState } from 'react';
import { RichTextEditor } from 'fc-react-rich-editor';

function App() {
  const [value, setValue] = useState([
    { type: 'paragraph', children: [{ text: 'Hello, World!' }] },
  ]);

  return (
    <RichTextEditor
      value={value}
      onChange={setValue}
      placeholder="Start writing..."
    />
  );
}

Styles are included with the component. For headless usage or custom CSS entry, import explicitly:

import 'fc-react-rich-editor/styles.css';

Usage

Basic props

PropTypeDescription
valueDescendant[]Controlled editor value (Slate JSON)
defaultValueDescendant[]Uncontrolled initial value
onChange(value: Descendant[]) => voidCalled when content changes
placeholderstringPlaceholder text
readOnlybooleanRead-only mode
autoFocusbooleanFocus editor on mount
minHeightnumber | stringMin height of the editable area (e.g. 200 or "20rem")
className / styleRoot container class and style
editorClassNamestringClass on the editable area

Images: upload, resize, align

Insert by URL – Use the toolbar image button or context menu; paste an image URL.

Insert by upload – Provide onImageUpload. The editor will show an “Upload” option; your callback uploads the file and returns the image URL.

<RichTextEditor
  value={value}
  onChange={setValue}
  onImageUpload={async (file: File) => {
    const formData = new FormData();
    formData.append('file', file);
    const res = await fetch('/api/upload', { method: 'POST', body: formData });
    const { url } = await res.json();
    return url; // must return the final image URL
  }}
/>

Resize – Select an image; a resize handle appears at the bottom-right corner. Drag to change width (80px–1200px).

Align – When an image is selected, use the alignment bar (left / center / right) below the image.

Tables

  • Insert – Toolbar or context menu → “Table” → choose rows (2–10) and columns (2–6).
  • Resize columns – Drag the column borders in the table header.
  • Add/remove – Right-click a cell for “Insert row above/below”, “Insert column left/right”, “Delete row/column”, “Delete table”.
  • Navigation – Tab moves to the next cell; Shift+Tab to the previous cell.

Video

Use the video button and paste a URL. Supports YouTube, Vimeo, Dailymotion, Loom, Wistia, or direct .mp4 / .webm / .ogg links.

Variables

Pass a list of variable names; users can insert them as chips (e.g. {{name}}, {{email}}).

<RichTextEditor
  value={value}
  onChange={setValue}
  variables={['name', 'email', 'company']}
/>

Slash menu (context menu) and custom commands

Right-click in the editor to open the context menu for inserting blocks and media. You can add custom commands (e.g. “Callout”, “Divider”) without writing a plugin:

import { Transforms } from 'slate';
import {
  RichTextEditor,
  type CustomContextMenuCommand,
  type SlashMenuConfig,
} from 'fc-react-rich-editor';

const customCommands: CustomContextMenuCommand[] = [
  {
    id: 'insert-callout',
    label: 'Callout',
    description: 'Insert a callout box',
    category: 'insert',
    keywords: ['callout', 'box', 'alert'],
    iconPaths: '<rect x="3" y="3" width="18" height="18" rx="2"/>',
    action: { type: 'custom', customId: 'insert-callout' },
  },
];

const slashConfig: SlashMenuConfig = {
  enabled: true,
  customCommands,
  onContextMenuCommand(customId, editor) {
    if (customId === 'insert-callout') {
      Transforms.insertNodes(editor, {
        type: 'paragraph',
        children: [{ text: 'Callout content...' }],
      });
    }
  },
};

<RichTextEditor
  value={value}
  onChange={setValue}
  slashMenu={slashConfig}
/>

Toolbar and hovering toolbar

  • Toolbartoolbar={true} (default), toolbar={false}, or a ToolbarConfig object with groups and items (marks, heading select, link, image, video, variable, table, alignment, etc.).
  • Hovering toolbar – Shown when text is selected. Use hoveringToolbar={true} (default), hoveringToolbar={false}, or an object to toggle items (bold, italic, link, font color, alignment, etc.) and set order.

Theming

Override theme tokens via the theme prop:

<RichTextEditor
  theme={{
    fontFamily: '"Inter", sans-serif',
    fontSize: '16px',
    focusRingColor: '#3b82f6',
    borderRadius: '8px',
    toolbarBg: '#f9fafb',
    linkColor: '#2563eb',
    // ... see RichTextTheme in types
  }}
/>

Serialization

import {
  htmlSerializer,
  markdownSerializer,
} from 'fc-react-rich-editor';

// Slate value → HTML
const html = htmlSerializer.serialize(value);

// HTML → Slate value
const slateValue = htmlSerializer.deserialize(htmlString);

// Slate value → Markdown
const markdown = markdownSerializer.serialize(value);

Live HTML / Markdown output

You can get HTML or Markdown on every change without calling the serializer yourself:

<RichTextEditor
  value={value}
  onChange={setValue}
  onHTMLChange={(html) => console.log(html)}
  onMarkdownChange={(md) => console.log(md)}
/>

Headless mode

Build your own UI around the same editor logic:

import { Slate } from 'slate-react';
import { useRichTextEditor } from 'fc-react-rich-editor';

function MyEditor() {
  const { editor, value, onChange, renderElement, renderLeaf } = useRichTextEditor();

  return (
    <Slate editor={editor} value={value} onChange={onChange}>
      <Editable
        renderElement={renderElement}
        renderLeaf={renderLeaf}
        placeholder="Write something..."
      />
    </Slate>
  );
}

Custom renderers

Override how elements or leaves are rendered; return undefined to fall back to the default:

<RichTextEditor
  renderElement={({ element, attributes, children }) => {
    if (element.type === 'paragraph') {
      return <p {...attributes} className="my-paragraph">{children}</p>;
    }
    return undefined;
  }}
  renderLeaf={({ leaf, attributes, children }) => {
    if (leaf.bold) {
      return <strong {...attributes}>{children}</strong>;
    }
    return undefined;
  }}
/>

Plugins

Pass an array of editor plugins to extend Slate behavior (e.g. custom insertData, isVoid, or new helpers):

import type { EditorPlugin } from 'fc-react-rich-editor';

const withMyFeature: EditorPlugin = (editor) => {
  const { insertText } = editor;
  editor.insertText = (text) => {
    // custom logic
    insertText(text);
  };
  return editor;
};

<RichTextEditor plugins={[withMyFeature]} value={value} onChange={setValue} />

See docs/PLUGINS.md for the full plugin guide and docs/ADDING_FEATURES.md for extending the editor with new features.

Adding more features

You can extend the editor in several ways without forking the package:

GoalHow
New context menu itemsUse slashMenu.customCommands and onContextMenuCommand. See Custom commands above and docs/PLUGINS.md.
New Slate behavior / node typesWrite an editor plugin and pass it in plugins. See docs/PLUGINS.md.
Custom block or inline renderingUse renderElement (and optionally a plugin for isVoid / normalization). See docs/ADDING_FEATURES.md.
Custom toolbar / hovering toolbarUse toolbar and hoveringToolbar config objects.
New themeUse the theme prop.

For a short “how to add features” guide, see docs/ADDING_FEATURES.md.

Exports

The package exports the main component, hooks, serializers, types, and Slate utilities so you don’t need to install slate for basic use:

  • Components: RichTextEditor, ThemeProvider
  • Hooks: useRichTextEditor
  • Serializers: htmlSerializer, markdownSerializer
  • Utils: createRichTextEditor, getBlockAlign, setBlockAlign, Transforms (re-export from Slate)
  • Types: Descendant, RichTextEditorProps, EditorPlugin, CustomElement, ImageElement, ImageAlign, ToolbarConfig, SlashMenuConfig, CustomContextMenuCommand, etc.

Author

Fahim Mahmud Chisti

License

MIT

Keywords

react

FAQs

Package last updated on 07 Jun 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts