UNPKG

@lax-wp/editor

Version:

A modern, feature-rich editor built with React and TipTap

725 lines (564 loc) 21.7 kB
# 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](#recent-updates) - [Features](#features) - [Installation](#installation) - [Quick Start](#quick-start) - [Configuration](#configuration) - [Basic Configuration](#basic-configuration) - [AI Autocompletion](#ai-autocompletion) - [Export Functionality](#export-functionality) - [Variable Text Feature](#variable-text-feature) - [Configuration Options Reference](#configuration-options-reference) - [Components](#components) - [Hooks](#hooks) - [API Reference](#api-reference) - [Examples](#examples) - [Development](#development) - [Contributing](#contributing) - [License](#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 - `useExport` hook for programmatic export functionality #### 📝 Variable Text Feature - Dynamic variable text support for mail merge and templates - Insert variables programmatically from your application - `onEditorReady` callback provides `insertVariable` method - 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 ```bash npm install lax-wp-editor # or yarn add lax-wp-editor # or pnpm add lax-wp-editor ``` ## Quick Start ```tsx 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:** > ```tsx > 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 ```tsx 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: ```tsx 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 `fetchCompletion` function. The editor does not include a default AI service. **Keyboard Shortcuts for AI Autocompletion:** - `Tab` - Accept suggestion - `Escape` - Dismiss suggestion - `Ctrl+Shift+Space` (Windows/Linux) or `Cmd+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: ```tsx 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 `useExport` hook 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:** ```tsx 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', 'newemail@example.com'); }; return ( <div> <button onClick={handleInsertName}>Insert User Name</button> <button onClick={handleInsertEmailWithValue}>Insert Email</button> <Editor config={{ enableVariableText: true, variableValues: { userName: 'John Doe', email: 'john@example.com', 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:** ```tsx insertVariable(key: string, value?: string) ``` - **`key`**: The variable name/key - **`value`**: (Optional) Update the variable value before inserting **How Variables Work:** 1. Variables are inserted as special nodes in the editor 2. They display the value from `variableValues` config 3. If no value exists, they display as `{{variableName}}` 4. Variables can be typed manually using `{{variableName}}` syntax (if enabled) 5. 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:** ```bash npm ls prosemirror-view # or yarn list prosemirror-view ``` **2. If you see multiple versions, add this to YOUR APPLICATION's `package.json`:** **For Yarn users:** ```json { "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+):** ```json { "overrides": { "prosemirror-view": "^1.41.0", "prosemirror-state": "^1.4.3", "prosemirror-model": "^1.25.0", "prosemirror-transform": "^1.10.0" } } ``` **For pnpm users:** ```json { "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:** ```bash # 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 install ``` **4. Verify all packages are deduped:** ```bash npm ls prosemirror-view # All instances should show "deduped" and point to the same version ``` > **Note:** This package uses `@tiptap/pm` internally (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 ```tsx import { Editor, ToolbarProvider } from 'lax-wp-editor'; import 'lax-wp-editor/styles'; function MyEditor() { return ( <ToolbarProvider> <Editor /> </ToolbarProvider> ); } ``` ### Custom Configuration ```tsx 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: 1. **Professional** - Multi-row toolbar with all options visible 2. **Classic** - Single-row compact toolbar with grouped controls 3. **Hide Toolbar** - No toolbar (presentation mode) ```tsx 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 component - **`ToolbarProvider`**: Context provider for toolbar state - **`Toolbar`**: Main toolbar component with tabbed interface - **`ProfessionalToolbar`**: 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 dropdown - **`HomeOptions`**: Basic formatting options - **`FontStyleOptions`**: Font styling options - **`ParagraphStyleOption`**: Paragraph styling - **`ExportOptions`**: Export functionality for multiple file formats - **`TableOptions`**: Table manipulation controls - **`InsertOptions`**: Insert various elements into the document ### Utility Components - **`SvgIcon`**: SVG icon component - **`PageSizeSelector`**: Page size and orientation selector - **`Button`**: Base button component - **`ColorPicker`**: Color picker for text and background colors ## Hooks - **`useTiptapEditorState`**: Access editor state - **`useHeadingStyleMethods`**: Heading manipulation methods - **`useFontStyleMethods`**: Font styling methods - **`useHomeOptionMethods`**: Basic formatting methods - **`useParagraphStyleMethods`**: Paragraph styling methods - **`usePageMethods`**: Page size and layout management - **`useExport`**: Export content in multiple formats (Text, JSON, Markdown, HTML) - **`useTableMethods`**: Table manipulation methods - **`useLinks`**: Link management methods - **`usePresentationMode`**: Presentation mode controls - **`useZoom`**: Zoom controls for the editor ## Configuration ### Editor Configuration ```tsx import { EditorConfig } from 'lax-wp-editor'; const config: EditorConfig = { // Your configuration options }; ``` ### Toolbar Types ```tsx 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 completely ``` The 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: ```tsx 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: ```tsx 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 ```tsx import { Editor, Toolbar, HeadingOptions, HomeOptions } from 'lax-wp-editor'; function CustomEditor() { return ( <div> <Toolbar> <HeadingOptions /> <HomeOptions /> </Toolbar> <Editor /> </div> ); } ``` ### Page Size Management ```tsx import { Editor, PageSizeSelector, usePageMethods } from 'lax-wp-editor'; function EditorWithPageSize() { const { pageSize, setPageSize } = usePageMethods(); return ( <div> <PageSizeSelector /> <Editor /> </div> ); } ``` ### Export Functionality ```tsx 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 ```tsx 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 ```bash npm run build ``` ### Linting ```bash npm run lint ``` ## Keywords `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: 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. 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: mdrifathasanshaun@gmail.com - GitHub: [@rifat-shaun](https://github.com/rifat-shaun) ## Support If you have any questions or need help, please: - Open an issue on [GitHub](https://github.com/rifat-shaun/wp-editor/issues) - Check the [documentation](https://github.com/rifat-shaun/wp-editor#readme) - Review the examples in this README