lax-wp-editor
v2.3.5
Published
A modern, feature-rich WordPress-style editor built with React and TipTap
Maintainers
Readme
Lax WP Editor
A modern, feature-rich WordPress-style editor built with React and TipTap. This editor provides a clean, intuitive interface for rich text editing with customizable toolbars and extensive formatting options.
Table of Contents
- Recent Updates
- Features
- Installation
- Quick Start
- Configuration
- Components
- Hooks
- API Reference
- Examples
- Development
- Contributing
- License
Recent Updates
v2.0.0 - Latest Release
✨ Export Functionality
- Added comprehensive export system with support for multiple formats
- Export your content as Text (.txt), JSON (.json), Markdown (.md), or HTML (.html)
- New Export tab in the toolbar for quick access to all export options
useExporthook for programmatic export functionality
📝 Variable Text Feature
- Dynamic variable text support for mail merge and templates
- Insert variables programmatically from your application
onEditorReadycallback providesinsertVariablemethod- Variables display actual values or
{{variableName}}placeholders - Supports manual typing with
{{variableName}}syntax
🎨 Toolbar Enhancements
- Improved toolbar dropdown with visual icons for each mode
- Better visual distinction between Professional, Classic, and Hide Toolbar modes
- Enhanced toolbar tab interface with 5 tabs: Home, Insert, Table, Page, and Export
- Smoother transitions between toolbar types
🖼️ Custom Image Support
- Resizable images with drag handles
- Image alignment (left, center, right)
- Bubble menu for image options
- Inline and block image support
Features
- 🎨 Modern UI: Clean, responsive design with customizable themes
- 📝 Rich Text Editing: Full-featured WYSIWYG editor with TipTap
- 🛠️ Flexible Toolbars: Professional and Classic toolbar modes with tabbed interface
- 📄 Page Management: Multiple page sizes and orientations
- 📤 Export Options: Export your content as Text, HTML, Markdown, or JSON
- 📝 Variable Text: Dynamic variables for mail merge and template systems
- 🖼️ Image Support: Resizable images with alignment and custom styling
- 🎯 Customizable: Easy to integrate and customize
- 📱 Responsive: Works seamlessly on desktop and mobile
- 🔧 TypeScript: Full TypeScript support with type definitions
Installation
npm install lax-wp-editor
# or
yarn add lax-wp-editor
# or
pnpm add lax-wp-editorQuick Start
import React from 'react';
import { Editor } from 'lax-wp-editor'; // CSS is automatically included!
function App() {
return (
<div style={{ height: '100vh', width: '100%' }}>
<Editor />
</div>
);
}
export default App;✨ New in v1.2.0: CSS is now automatically imported! You no longer need to manually import the styles.
For older versions (v1.1.x), you need to manually import styles:
import 'lax-wp-editor/styles'; // or import 'lax-wp-editor/dist/lax-wp-editor.css';
Configuration
The editor accepts a config prop with the following options:
Basic Configuration
import { Editor, type EditorConfig } from 'lax-wp-editor';
function App() {
const config: EditorConfig = {
// Initial content (HTML string)
content: '<p>Your initial content here</p>',
// Toolbar type: 'professional' or 'classic'
defaultToolbar: 'professional',
// Enable/disable features
showBubbleMenu: true, // Show bubble menu on text selection
showFloatingMenu: false, // Show floating menu on empty lines
showPageSizeSelector: true, // Show page size selector
enablePagination: true, // Enable pagination
// Content change callback with debounce
debounceTimeForContentChange: 300, // Debounce time in milliseconds (default: 300ms)
onContentChange: (editor) => {
const html = editor.getHTML();
console.log('Content changed:', html);
},
};
return (
<div style={{ height: '100vh', width: '100%' }}>
<Editor config={config} />
</div>
);
}AI Autocompletion
You can enable AI autocompletion by providing your own completion function:
import { Editor, type EditorConfig } from 'lax-wp-editor';
function App() {
const config: EditorConfig = {
aiAutocompletion: {
enabled: true,
minWordsToTriggerAutoCompletion: 5, // Trigger after 5 words (default: 3)
debounceTime: 300, // Wait 300ms before calling API (default: 100ms)
// Required: Provide your custom fetch function
fetchCompletion: async (text: string) => {
const response = await fetch('https://your-api.com/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY',
},
body: JSON.stringify({ prompt: text }),
});
const data = await response.json();
return data.completion; // Return the completion text
},
},
};
return (
<div style={{ height: '100vh', width: '100%' }}>
<Editor config={config} />
</div>
);
}⚠️ Important: AI autocompletion requires you to provide a
fetchCompletionfunction. The editor does not include a default AI service.
Keyboard Shortcuts for AI Autocompletion:
Tab- Accept suggestionEscape- Dismiss suggestionCtrl+Shift+Space(Windows/Linux) orCmd+Shift+Space(Mac) - Toggle autocompletion on/off
Export Functionality
The editor includes a comprehensive export system that allows users to download their content in multiple formats:
import { Editor, useExport } from 'lax-wp-editor';
function MyEditorComponent({ editor }) {
const {
downloadTextFile,
downloadJsonFile,
downloadMarkdownFile,
downloadHtmlFile
} = useExport(editor);
return (
<div>
<button onClick={downloadTextFile}>Export as Text</button>
<button onClick={downloadJsonFile}>Export as JSON</button>
<button onClick={downloadMarkdownFile}>Export as Markdown</button>
<button onClick={downloadHtmlFile}>Export as HTML</button>
</div>
);
}Available Export Formats:
| Format | Description | Method |
|--------|-------------|--------|
| Text | Plain text (.txt) | downloadTextFile() |
| JSON | TipTap JSON format (.json) | downloadJsonFile() |
| Markdown | Markdown format (.md) | downloadMarkdownFile() |
| HTML | HTML format (.html) | downloadHtmlFile() |
💡 Tip: The Export tab is built into the toolbar and provides quick access to all export formats. You can also use the
useExporthook to create custom export buttons.
Variable Text Feature
The editor supports dynamic variable text that can be inserted programmatically from your application. Variables are displayed as placeholders that get replaced with actual values.
Enable Variable Text:
import { useState } from 'react';
import { Editor } from 'lax-wp-editor';
function App() {
const [insertVariable, setInsertVariable] = useState<((key: string, value?: string) => void) | null>(null);
const handleInsertName = () => {
insertVariable?.('userName');
};
const handleInsertEmailWithValue = () => {
insertVariable?.('email', '[email protected]');
};
return (
<div>
<button onClick={handleInsertName}>Insert User Name</button>
<button onClick={handleInsertEmailWithValue}>Insert Email</button>
<Editor
config={{
enableVariableText: true,
variableValues: {
userName: 'John Doe',
email: '[email protected]',
company: 'Acme Inc',
},
onEditorReady: ({ insertVariable: insert }) => {
// Store the insertVariable method when editor is ready
setInsertVariable(() => insert);
},
}}
/>
</div>
);
}Variable Text Configuration:
| Option | Type | Description |
|--------|------|-------------|
| enableVariableText | boolean | Enable/disable variable text feature |
| variableValues | Record<string, string> | Key-value pairs for variable replacements |
| onEditorReady | (methods) => void | Callback that provides editor methods including insertVariable |
Insert Variable Method:
insertVariable(key: string, value?: string)key: The variable name/keyvalue: (Optional) Update the variable value before inserting
How Variables Work:
- Variables are inserted as special nodes in the editor
- They display the value from
variableValuesconfig - If no value exists, they display as
{{variableName}} - Variables can be typed manually using
{{variableName}}syntax (if enabled) - Users can insert variables programmatically from outside the editor
Example Use Cases:
- Mail merge functionality
- Template systems
- Dynamic content generation
- Personalized documents
Configuration Options Reference
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| content | string | "" | Initial HTML content for the editor |
| defaultToolbar | 'professional' \| 'classic' | 'professional' | Toolbar style |
| showBubbleMenu | boolean | true | Show bubble menu on text selection |
| showFloatingMenu | boolean | false | Show floating menu on empty lines |
| showPageSizeSelector | boolean | true | Show page size selector |
| enablePagination | boolean | true | Enable pagination |
| debounceTimeForContentChange | number | 300 | Debounce time (ms) for onContentChange callback |
| onContentChange | (editor: Editor) => void | undefined | Callback when content changes (debounced) |
| enableVariableText | boolean | false | Enable variable text feature |
| variableValues | Record<string, string> | {} | Variable name to value mappings |
| onEditorReady | (methods) => void | undefined | Callback with editor methods when ready |
| onShare | () => void | undefined | Callback when share button is clicked |
| aiAutocompletion | AIAutocompletionConfig | See below | AI autocompletion configuration |
AIAutocompletionConfig:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enabled | boolean | false | Enable/disable AI autocompletion |
| minWordsToTriggerAutoCompletion | number | 3 | Minimum words to trigger autocompletion |
| debounceTime | number | 100 | Debounce time (ms) before calling API |
| fetchCompletion | (text: string) => Promise<string> | undefined | Required - Custom fetch function for AI completions |
Important: Fixing ProseMirror Duplication Error
If you encounter the localsInner error, it's caused by multiple versions of ProseMirror packages in your application's dependency tree.
Official Tiptap Solution:
This package already uses @tiptap/pm for all ProseMirror functionality (as recommended by Tiptap). However, you need to ensure your application also deduplicates ProseMirror versions.
1. In your application directory, check for duplicate ProseMirror versions:
npm ls prosemirror-view
# or
yarn list prosemirror-view2. If you see multiple versions, add this to YOUR APPLICATION's package.json:
For Yarn users:
{
"resolutions": {
"prosemirror-view": "^1.41.0",
"prosemirror-state": "^1.4.3",
"prosemirror-model": "^1.25.0",
"prosemirror-transform": "^1.10.0"
}
}For npm users (v8.3.0+):
{
"overrides": {
"prosemirror-view": "^1.41.0",
"prosemirror-state": "^1.4.3",
"prosemirror-model": "^1.25.0",
"prosemirror-transform": "^1.10.0"
}
}For pnpm users:
{
"pnpm": {
"overrides": {
"prosemirror-view": "^1.41.0",
"prosemirror-state": "^1.4.3",
"prosemirror-model": "^1.25.0",
"prosemirror-transform": "^1.10.0"
}
}
}3. Clean install in YOUR APPLICATION:
# In your application directory (not lax-wp-editor)
rm -rf node_modules package-lock.json # or yarn.lock / pnpm-lock.yaml
npm install # or yarn / pnpm install4. Verify all packages are deduped:
npm ls prosemirror-view
# All instances should show "deduped" and point to the same versionNote: This package uses
@tiptap/pminternally (not direct ProseMirror imports) to prevent version conflicts. The deduplication step is only needed if other packages in your project import ProseMirror directly.
Basic Usage
Simple Editor
import { Editor, ToolbarProvider } from 'lax-wp-editor';
import 'lax-wp-editor/styles';
function MyEditor() {
return (
<ToolbarProvider>
<Editor />
</ToolbarProvider>
);
}Custom Configuration
import { Editor, ToolbarProvider, defaultEditorConfig } from 'lax-wp-editor';
import 'lax-wp-editor/styles';
function MyEditor() {
const config = {
...defaultEditorConfig,
// Add your custom configuration
};
return (
<ToolbarProvider>
<Editor config={config} />
</ToolbarProvider>
);
}Different Toolbar Types
The editor supports three toolbar modes:
- Professional - Multi-row toolbar with all options visible
- Classic - Single-row compact toolbar with grouped controls
- Hide Toolbar - No toolbar (presentation mode)
import { Editor, ToolbarProvider, TOOLBAR_TYPES_ENUM } from 'lax-wp-editor';
import 'lax-wp-editor/styles';
function MyEditor() {
return (
<ToolbarProvider initialToolbar={TOOLBAR_TYPES_ENUM.CLASSIC}>
<Editor />
</ToolbarProvider>
);
}Users can switch between toolbar modes using the built-in toolbar dropdown menu, which includes icons for each mode:
- 📊 Classic - Compact view
- 🎛️ Professional - Full view
- 👁️ Hide Toolbar - Hidden view
Components
Main Components
Editor: The main editor componentToolbarProvider: Context provider for toolbar stateToolbar: Main toolbar component with tabbed interfaceProfessionalToolbar: Professional-style toolbar (multi-row layout)ClassicToolbar: Classic-style toolbar (single-row layout)ToolbarDropdown: Dropdown to switch between toolbar modes
Toolbar Tabs
The editor includes a tabbed toolbar interface with the following tabs:
Home: Basic formatting options (bold, italic, underline, alignment, etc.)Insert: Insert elements (tables, images, dividers, etc.)Table: Table-specific operations (add/remove rows/columns, merge cells, etc.)Page: Page settings (size, orientation, margins, background)Export: Export content in multiple formats (Text, JSON, Markdown, HTML)
Individual Toolbar Components
HeadingOptions: Heading selection dropdownHomeOptions: Basic formatting optionsFontStyleOptions: Font styling optionsParagraphStyleOption: Paragraph stylingExportOptions: Export functionality for multiple file formatsTableOptions: Table manipulation controlsInsertOptions: Insert various elements into the document
Utility Components
SvgIcon: SVG icon componentPageSizeSelector: Page size and orientation selectorButton: Base button componentColorPicker: Color picker for text and background colors
Hooks
useTiptapEditorState: Access editor stateuseHeadingStyleMethods: Heading manipulation methodsuseFontStyleMethods: Font styling methodsuseHomeOptionMethods: Basic formatting methodsuseParagraphStyleMethods: Paragraph styling methodsusePageMethods: Page size and layout managementuseExport: Export content in multiple formats (Text, JSON, Markdown, HTML)useTableMethods: Table manipulation methodsuseLinks: Link management methodsusePresentationMode: Presentation mode controlsuseZoom: Zoom controls for the editor
Configuration
Editor Configuration
import { EditorConfig } from 'lax-wp-editor';
const config: EditorConfig = {
// Your configuration options
};Toolbar Types
import { TOOLBAR_TYPES_ENUM } from 'lax-wp-editor';
// Available toolbar types:
TOOLBAR_TYPES_ENUM.PROFESSIONAL // Professional toolbar (multi-row, all options visible)
TOOLBAR_TYPES_ENUM.CLASSIC // Classic toolbar (single-row, compact)
TOOLBAR_TYPES_ENUM.HIDE_TOOLBAR // Hide toolbar completelyThe toolbar includes 5 tabs:
- Home: Text formatting, alignment, lists, etc.
- Insert: Tables, images, dividers, and other insertable elements
- Table: Table-specific operations (add/remove rows/columns, merge cells)
- Page: Page layout settings (size, orientation, margins, background)
- Export: Download content in various formats (Text, JSON, Markdown, HTML)
Styling
The package includes default styles that you can import:
import 'lax-wp-editor/styles';You can also customize the styles by overriding CSS variables or using your own CSS.
TypeScript Support
The package includes full TypeScript definitions:
import { Editor, EditorConfig, PageSize } from 'lax-wp-editor';API Reference
Editor Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| config | EditorConfig | defaultEditorConfig | Editor configuration |
| onUpdate | (content: string) => void | - | Callback when content changes |
| initialContent | string | - | Initial editor content |
ToolbarProvider Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| initialToolbar | ToolbarType | PROFESSIONAL | Initial toolbar type |
| children | ReactNode | - | Child components |
ToolbarDropdown Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onToolbarChange | (toolbarType: string) => void | - | Callback when toolbar type changes |
useExport Hook
Returns an object with the following methods:
| Method | Description |
|--------|-------------|
| downloadTextFile() | Downloads content as plain text (.txt) |
| downloadJsonFile() | Downloads content as TipTap JSON format (.json) |
| downloadMarkdownFile() | Downloads content as Markdown (.md) |
| downloadHtmlFile() | Downloads content as HTML (.html) |
Examples
Custom Toolbar
import { Editor, Toolbar, HeadingOptions, HomeOptions } from 'lax-wp-editor';
function CustomEditor() {
return (
<div>
<Toolbar>
<HeadingOptions />
<HomeOptions />
</Toolbar>
<Editor />
</div>
);
}Page Size Management
import { Editor, PageSizeSelector, usePageMethods } from 'lax-wp-editor';
function EditorWithPageSize() {
const { pageSize, setPageSize } = usePageMethods();
return (
<div>
<PageSizeSelector />
<Editor />
</div>
);
}Export Functionality
import { Editor, useExport } from 'lax-wp-editor';
function EditorWithExport() {
const editorRef = useRef(null);
const {
downloadTextFile,
downloadJsonFile,
downloadMarkdownFile,
downloadHtmlFile
} = useExport(editorRef.current);
return (
<div>
<div className="export-buttons">
<button onClick={downloadTextFile}>Download as Text</button>
<button onClick={downloadJsonFile}>Download as JSON</button>
<button onClick={downloadMarkdownFile}>Download as Markdown</button>
<button onClick={downloadHtmlFile}>Download as HTML</button>
</div>
<Editor ref={editorRef} />
</div>
);
}Switching Toolbar Modes
import { Editor, ToolbarProvider, ToolbarDropdown } from 'lax-wp-editor';
function EditorWithToolbarSwitch() {
return (
<ToolbarProvider>
<ToolbarDropdown onToolbarChange={(type) => console.log('Toolbar changed to:', type)} />
<Editor />
</ToolbarProvider>
);
}Development
Building the Package
npm run buildRunning Storybook
npm run storybookLinting
npm run lintKeywords
wysiwyg, editor, react, tiptap, wordpress, rich-text, text-editor, markdown, html-editor, document-editor, export, typescript
Contributing
Contributions are welcome! Here's how you can help:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to:
- Follow the existing code style
- Add tests for new features
- Update documentation as needed
- Test your changes thoroughly
License
MIT © Rifat Hasan Shaun
Author
Rifat Hasan Shaun
- Email: [email protected]
- GitHub: @rifat-shaun
Support
If you have any questions or need help, please:
- Open an issue on GitHub
- Check the documentation
- Review the examples in this README
