rte-builder 2.0.5 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,505 +1,505 @@
1
- # RTE Builder
2
-
3
- A **universal, adapter-based** rich text editor library for React that supports multiple editor backends. Built to be **editor-agnostic** with a unified API.
4
-
5
- ## Features
6
-
7
- - **Multiple Editor Support**: TipTap, Slate.js, and Lexical (all included)
8
- - **Unified API**: Same interface works with any editor
9
- - **Editor Registry**: Dynamically register and switch between editors
10
- - **Full Feature Set**: 50+ toolbar buttons, code highlighting, tables, media, and more
11
- - **TypeScript First**: Complete type definitions with strict mode
12
- - **Zero License Costs**: All included editors are MIT licensed
13
- - **Customizable**: Toolbar presets, custom extensions, styling
14
-
15
- ## Supported Editors
16
-
17
- | Editor | Status | Bundle Size | Description |
18
- | ------------ | ----------- | ----------- | ------------------------------------ |
19
- | **TipTap** | ✅ Included | ~280KB | ProseMirror-based, highly extensible |
20
- | **Slate.js** | ✅ Included | ~150KB | Completely customizable framework |
21
- | **Lexical** | ✅ Included | ~100KB | Meta's modern editor framework |
22
- | **Quill** | 📋 Backlog | ~50KB | Simple, lightweight editor |
23
- | **Draft.js** | 📋 Backlog | ~200KB | React-first by Facebook |
24
-
25
- ## 🎯 Try the Demo
26
-
27
- ```bash
28
- cd d:\projects\GrabOn\rte-builder
29
- npm run demo:install
30
- npm run demo
31
- ```
32
-
33
- ## Installation
34
-
35
- ```bash
36
- npm install rte-builder
37
- ```
38
-
39
- ## Quick Start
40
-
41
- ### Basic Usage (TipTap - Default)
42
-
43
- ```tsx
44
- import { RichTextEditor } from "rte-builder";
45
-
46
- function App() {
47
- const [content, setContent] = useState("");
48
-
49
- return (
50
- <RichTextEditor
51
- value={content}
52
- onChange={setContent}
53
- placeholder="Start typing..."
54
- height={400}
55
- />
56
- );
57
- }
58
- ```
59
-
60
- ### Using the Unified Editor (Recommended)
61
-
62
- ```tsx
63
- import { UnifiedEditor } from "rte-builder";
64
- import type { UnifiedEditorRef } from "rte-builder";
65
-
66
- function App() {
67
- const editorRef = useRef<UnifiedEditorRef>(null);
68
- const [content, setContent] = useState("");
69
-
70
- return (
71
- <UnifiedEditor
72
- editor="tiptap" // Optional: explicitly select editor
73
- value={content}
74
- onChange={setContent}
75
- toolbar="full" // Use preset: 'full' | 'medium' | 'simple' | 'minimal'
76
- showCharCounter
77
- charCounterMax={5000}
78
- />
79
- );
80
- }
81
- ```
82
-
83
- ### With Custom Toolbar
84
-
85
- ```tsx
86
- import { RichTextEditor, customizeToolbar } from "rte-builder";
87
-
88
- // Create custom toolbar from preset
89
- const myToolbar = customizeToolbar("medium", {
90
- remove: ["table", "video"],
91
- add: ["emoji", "fullscreen"],
92
- });
93
-
94
- // Or define explicitly
95
- const myToolbar = [
96
- "bold",
97
- "italic",
98
- "underline",
99
- "separator",
100
- "heading1",
101
- "heading2",
102
- "separator",
103
- "bulletList",
104
- "orderedList",
105
- "separator",
106
- "link",
107
- "image",
108
- "separator",
109
- "undo",
110
- "redo",
111
- ];
112
-
113
- function App() {
114
- return (
115
- <RichTextEditor
116
- value={content}
117
- onChange={setContent}
118
- toolbarButtons={myToolbar}
119
- />
120
- );
121
- }
122
- ```
123
-
124
- ### With Media Picker Integration
125
-
126
- ```tsx
127
- import { RichTextEditor } from "rte-builder";
128
- import type { MediaFile } from "rte-builder";
129
-
130
- function App() {
131
- const handleImagePicker = async (): Promise<MediaFile | null> => {
132
- // Open your media picker dialog
133
- const file = await openYourMediaPicker("image");
134
-
135
- if (file) {
136
- return {
137
- url: file.url,
138
- name: file.name,
139
- alt: file.name,
140
- };
141
- }
142
- return null;
143
- };
144
-
145
- const handleVideoPicker = async (): Promise<MediaFile | null> => {
146
- const file = await openYourMediaPicker("video");
147
- return file ? { url: file.url, name: file.name } : null;
148
- };
149
-
150
- return (
151
- <RichTextEditor
152
- value={content}
153
- onChange={setContent}
154
- onMediaPickerImage={handleImagePicker}
155
- onMediaPickerVideo={handleVideoPicker}
156
- />
157
- );
158
- }
159
- ```
160
-
161
- ## API Reference
162
-
163
- ### Component Props
164
-
165
- | Prop | Type | Default | Description |
166
- | --------------------- | ---------------------------------- | ------------------- | ------------------------------- |
167
- | `value` | `string` | `''` | HTML content |
168
- | `onChange` | `(content: string) => void` | - | Content change handler |
169
- | `onBlur` | `() => void` | - | Blur event handler |
170
- | `onFocus` | `() => void` | - | Focus event handler |
171
- | `placeholder` | `string` | `'Start typing...'` | Placeholder text |
172
- | `height` | `number` | `400` | Editor height in pixels |
173
- | `minHeight` | `number` | `300` | Minimum height |
174
- | `maxHeight` | `number` | - | Maximum height |
175
- | `disabled` | `boolean` | `false` | Disable editing |
176
- | `readOnly` | `boolean` | `false` | Read-only mode |
177
- | `charCounterMax` | `number` | `-1` | Character limit (-1 = no limit) |
178
- | `showCharCounter` | `boolean` | `false` | Show character count |
179
- | `toolbarPreset` | `'full' \| 'medium' \| 'simple'` | `'full'` | Toolbar preset |
180
- | `toolbarButtons` | `ToolbarButton[]` | - | Custom toolbar buttons |
181
- | `className` | `string` | `''` | Additional CSS class |
182
- | `onMediaPickerImage` | `() => Promise<MediaFile \| null>` | - | Image picker callback |
183
- | `onMediaPickerVideo` | `() => Promise<MediaFile \| null>` | - | Video picker callback |
184
- | `enableCodeHighlight` | `boolean` | `true` | Enable syntax highlighting |
185
- | `defaultCodeLanguage` | `string` | `'javascript'` | Default code language |
186
-
187
- ### Ref Methods
188
-
189
- ```tsx
190
- const editorRef = useRef<EditorRef>(null);
191
-
192
- // Get content
193
- const html = editorRef.current?.getContent();
194
- const text = editorRef.current?.getText();
195
- const json = editorRef.current?.getJSON();
196
-
197
- // Set content
198
- editorRef.current?.setContent("<p>Hello World</p>");
199
-
200
- // Navigation
201
- editorRef.current?.focus();
202
- editorRef.current?.blur();
203
-
204
- // Insert
205
- editorRef.current?.insertHTML("<strong>Bold text</strong>");
206
- editorRef.current?.insertText("Plain text");
207
-
208
- // Clear
209
- editorRef.current?.clear();
210
-
211
- // State
212
- const empty = editorRef.current?.isEmpty();
213
- const chars = editorRef.current?.getCharacterCount();
214
- const words = editorRef.current?.getWordCount();
215
-
216
- // History
217
- editorRef.current?.undo();
218
- editorRef.current?.redo();
219
- const canUndo = editorRef.current?.canUndo();
220
- const canRedo = editorRef.current?.canRedo();
221
-
222
- // Actions
223
- editorRef.current?.toggleFullscreen();
224
- editorRef.current?.print();
225
-
226
- // Native editor access
227
- const tiptapEditor = editorRef.current?.getNativeEditor();
228
- ```
229
-
230
- ### Toolbar Buttons
231
-
232
- All available toolbar buttons:
233
-
234
- **Text Formatting:**
235
- `bold`, `italic`, `underline`, `strike`, `code`, `codeBlock`, `subscript`, `superscript`, `clearFormatting`
236
-
237
- **Font & Colors:**
238
- `fontFamily`, `fontSize`, `lineHeight`, `textColor`, `backgroundColor`
239
-
240
- **Alignment & Indentation:**
241
- `alignLeft`, `alignCenter`, `alignRight`, `alignJustify`, `indent`, `outdent`
242
-
243
- **Lists:**
244
- `bulletList`, `orderedList`
245
-
246
- **Headings:**
247
- `heading1`, `heading2`, `heading3`, `heading4`, `heading5`, `heading6`
248
-
249
- **Blocks:**
250
- `blockquote`, `horizontalRule`
251
-
252
- **Links & Media:**
253
- `link`, `unlink`, `image`, `video`, `table`, `emoji`
254
-
255
- **Actions:**
256
- `undo`, `redo`, `fullscreen`, `print`
257
-
258
- **Special:**
259
- `separator`
260
-
261
- ### Toolbar Presets
262
-
263
- ```tsx
264
- import { toolbarPresets, getToolbarPreset } from "rte-builder";
265
-
266
- // Available presets
267
- const full = getToolbarPreset("full"); // All features (50+ buttons)
268
- const medium = getToolbarPreset("medium"); // Standard features (30+ buttons)
269
- const simple = getToolbarPreset("simple"); // Basic features (12 buttons)
270
- const minimal = getToolbarPreset("minimal"); // Just essentials (7 buttons)
271
- const code = getToolbarPreset("code"); // For technical docs
272
- const blog = getToolbarPreset("blog"); // For blog posts
273
- const email = getToolbarPreset("email"); // For email composition
274
- ```
275
-
276
- ## Editor Registry
277
-
278
- Register custom editors or check availability:
279
-
280
- ```tsx
281
- import {
282
- EditorRegistry,
283
- registerAdapter,
284
- isEditorAvailable,
285
- getAvailableAdapters,
286
- getEditorFeatures,
287
- } from "rte-builder";
288
-
289
- // Check what's available
290
- const available = getAvailableAdapters();
291
- console.log(available.map((a) => a.name));
292
-
293
- // Check specific editor
294
- if (isEditorAvailable("tiptap")) {
295
- console.log("TipTap is ready!");
296
- }
297
-
298
- // Get feature comparison
299
- const features = getEditorFeatures("tiptap");
300
- console.log(features.tables); // true
301
- console.log(features.collaboration); // false
302
- ```
303
-
304
- ## Custom Extensions (TipTap)
305
-
306
- The library exports TipTap extensions for advanced use:
307
-
308
- ```tsx
309
- import {
310
- FontSize,
311
- LineHeight,
312
- Video,
313
- Emoji,
314
- Fullscreen,
315
- Print,
316
- Indent,
317
- EMOJI_CATEGORIES,
318
- } from "rte-builder";
319
-
320
- // Use with TipTap directly
321
- import { useEditor } from "@tiptap/react";
322
-
323
- const editor = useEditor({
324
- extensions: [
325
- // ... other extensions
326
- FontSize,
327
- LineHeight,
328
- Fullscreen,
329
- ],
330
- });
331
- ```
332
-
333
- ## Styling
334
-
335
- The library includes comprehensive CSS. You can customize via CSS variables:
336
-
337
- ```css
338
- /* Override in your CSS */
339
- .rte-builder-wrapper {
340
- --editor-border-color: #e5e7eb;
341
- --editor-background: #ffffff;
342
- --toolbar-background: #f9fafb;
343
- --button-active-color: #3b82f6;
344
- --text-color: #1f2937;
345
- }
346
-
347
- /* Or use custom classes */
348
- .my-editor .rte-builder-toolbar {
349
- background: #1a1a1a;
350
- }
351
- ```
352
-
353
- ## Project Structure
354
-
355
- ```
356
- rte-builder/
357
- ├── src/
358
- │ ├── core/ # Core types, registry, presets
359
- │ │ ├── types.ts # Unified type definitions
360
- │ │ ├── registry.ts # Editor adapter registry
361
- │ │ └── presets.ts # Toolbar presets
362
- │ ├── adapters/ # Editor implementations
363
- │ │ ├── tiptap/ # TipTap adapter (included)
364
- │ │ ├── slate/ # Slate.js adapter (included)
365
- │ │ └── lexical/ # Lexical adapter (included)
366
- │ ├── components/ # React components
367
- │ │ ├── RichTextEditor.tsx # Legacy TipTap component
368
- │ │ └── UnifiedEditor.tsx # New unified component
369
- │ ├── extensions/ # Custom TipTap extensions
370
- │ └── styles/ # CSS styles
371
- ├── dist/ # Built output
372
- ├── README.md
373
- └── package.json
374
- ```
375
-
376
- ## Roadmap
377
-
378
- - [x] **v1.0**: Complete TipTap implementation
379
- - [x] **v1.1**: Generic adapter architecture
380
- - [x] **v1.2**: Slate.js adapter
381
- - [x] **v1.3**: Lexical adapter
382
- - [x] **v2.0**: Collaborative editing
383
- - [x] **v2.1**: Comments & annotations
384
- - [x] **v2.2**: Version history
385
- - [ ] **v2.3**: Quill adapter
386
- - [ ] **v2.4**: Draft.js adapter
387
-
388
- ## Collaborative Editing (v2.0)
389
-
390
- Enable real-time collaboration with presence indicators:
391
-
392
- ```tsx
393
- import { UnifiedEditor, CollaborationProvider, PresenceIndicator } from 'rte-builder'
394
-
395
- function CollaborativeEditor() {
396
- return (
397
- <CollaborationProvider
398
- config={{
399
- provider: 'websocket',
400
- serverUrl: 'wss://your-server.com/collab',
401
- roomId: 'document-123',
402
- user: {
403
- id: 'user-1',
404
- name: 'John Doe',
405
- color: '#3b82f6',
406
- },
407
- }}
408
- onStatusChange={(status) => console.log('Status:', status)}
409
- onUsersChange={(users) => console.log('Users:', users)}
410
- >
411
- <PresenceIndicator />
412
- <UnifiedEditor
413
- value={content}
414
- onChange={setContent}
415
- />
416
- </CollaborationProvider>
417
- )
418
- }
419
- ```
420
-
421
- ## Comments & Annotations (v2.1)
422
-
423
- Add inline comments and annotations to your documents:
424
-
425
- ```tsx
426
- import { UnifiedEditor, CommentsProvider, CommentsPanel } from 'rte-builder'
427
-
428
- function EditorWithComments() {
429
- return (
430
- <CommentsProvider
431
- config={{
432
- currentUser: {
433
- id: 'user-1',
434
- name: 'John Doe',
435
- },
436
- allowResolve: true,
437
- allowReactions: true,
438
- }}
439
- onThreadsChange={(threads) => saveThreads(threads)}
440
- >
441
- <div style={{ display: 'flex' }}>
442
- <UnifiedEditor
443
- value={content}
444
- onChange={setContent}
445
- />
446
- <CommentsPanel position="right" />
447
- </div>
448
- </CommentsProvider>
449
- )
450
- }
451
- ```
452
-
453
- ## Version History (v2.2)
454
-
455
- Track and restore document versions:
456
-
457
- ```tsx
458
- import { UnifiedEditor, VersionHistoryProvider, VersionHistoryPanel } from 'rte-builder'
459
-
460
- function EditorWithHistory() {
461
- const editorRef = useRef(null)
462
-
463
- return (
464
- <VersionHistoryProvider
465
- config={{
466
- currentUser: {
467
- id: 'user-1',
468
- name: 'John Doe',
469
- },
470
- autoSave: true,
471
- autoSaveInterval: 60000, // 1 minute
472
- maxVersions: 100,
473
- onRestore: (version) => {
474
- editorRef.current?.setContent(version.content)
475
- },
476
- }}
477
- getCurrentContent={() => ({
478
- html: editorRef.current?.getContent() || '',
479
- text: editorRef.current?.getText() || '',
480
- })}
481
- >
482
- <div style={{ display: 'flex' }}>
483
- <UnifiedEditor
484
- ref={editorRef}
485
- value={content}
486
- onChange={setContent}
487
- />
488
- <VersionHistoryPanel position="right" />
489
- </div>
490
- </VersionHistoryProvider>
491
- )
492
- }
493
- ```
494
-
495
- ## License
496
-
497
- MIT License - Free for commercial and personal use.
498
-
499
- ## Contributing
500
-
501
- Contributions welcome! Please read our contributing guidelines.
502
-
503
- ## Support
504
-
505
- - GitHub Issues: Report bugs or request features
1
+ # RTE Builder
2
+
3
+ A **universal, adapter-based** rich text editor library for React that supports multiple editor backends. Built to be **editor-agnostic** with a unified API.
4
+
5
+ ## Features
6
+
7
+ - **Multiple Editor Support**: TipTap, Slate.js, and Lexical (all included)
8
+ - **Unified API**: Same interface works with any editor
9
+ - **Editor Registry**: Dynamically register and switch between editors
10
+ - **Full Feature Set**: 50+ toolbar buttons, code highlighting, tables, media, and more
11
+ - **TypeScript First**: Complete type definitions with strict mode
12
+ - **Zero License Costs**: All included editors are MIT licensed
13
+ - **Customizable**: Toolbar presets, custom extensions, styling
14
+
15
+ ## Supported Editors
16
+
17
+ | Editor | Status | Bundle Size | Description |
18
+ | ------------ | ----------- | ----------- | ------------------------------------ |
19
+ | **TipTap** | ✅ Included | ~280KB | ProseMirror-based, highly extensible |
20
+ | **Slate.js** | ✅ Included | ~150KB | Completely customizable framework |
21
+ | **Lexical** | ✅ Included | ~100KB | Meta's modern editor framework |
22
+ | **Quill** | 📋 Backlog | ~50KB | Simple, lightweight editor |
23
+ | **Draft.js** | 📋 Backlog | ~200KB | React-first by Facebook |
24
+
25
+ ## 🎯 Try the Demo
26
+
27
+ ```bash
28
+ cd d:\projects\GrabOn\rte-builder
29
+ npm run demo:install
30
+ npm run demo
31
+ ```
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ npm install rte-builder
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ### Basic Usage (TipTap - Default)
42
+
43
+ ```tsx
44
+ import { RichTextEditor } from "rte-builder";
45
+
46
+ function App() {
47
+ const [content, setContent] = useState("");
48
+
49
+ return (
50
+ <RichTextEditor
51
+ value={content}
52
+ onChange={setContent}
53
+ placeholder="Start typing..."
54
+ height={400}
55
+ />
56
+ );
57
+ }
58
+ ```
59
+
60
+ ### Using the Unified Editor (Recommended)
61
+
62
+ ```tsx
63
+ import { UnifiedEditor } from "rte-builder";
64
+ import type { UnifiedEditorRef } from "rte-builder";
65
+
66
+ function App() {
67
+ const editorRef = useRef<UnifiedEditorRef>(null);
68
+ const [content, setContent] = useState("");
69
+
70
+ return (
71
+ <UnifiedEditor
72
+ editor="tiptap" // Optional: explicitly select editor
73
+ value={content}
74
+ onChange={setContent}
75
+ toolbar="full" // Use preset: 'full' | 'medium' | 'simple' | 'minimal'
76
+ showCharCounter
77
+ charCounterMax={5000}
78
+ />
79
+ );
80
+ }
81
+ ```
82
+
83
+ ### With Custom Toolbar
84
+
85
+ ```tsx
86
+ import { RichTextEditor, customizeToolbar } from "rte-builder";
87
+
88
+ // Create custom toolbar from preset
89
+ const myToolbar = customizeToolbar("medium", {
90
+ remove: ["table", "video"],
91
+ add: ["emoji", "fullscreen"],
92
+ });
93
+
94
+ // Or define explicitly
95
+ const myToolbar = [
96
+ "bold",
97
+ "italic",
98
+ "underline",
99
+ "separator",
100
+ "heading1",
101
+ "heading2",
102
+ "separator",
103
+ "bulletList",
104
+ "orderedList",
105
+ "separator",
106
+ "link",
107
+ "image",
108
+ "separator",
109
+ "undo",
110
+ "redo",
111
+ ];
112
+
113
+ function App() {
114
+ return (
115
+ <RichTextEditor
116
+ value={content}
117
+ onChange={setContent}
118
+ toolbarButtons={myToolbar}
119
+ />
120
+ );
121
+ }
122
+ ```
123
+
124
+ ### With Media Picker Integration
125
+
126
+ ```tsx
127
+ import { RichTextEditor } from "rte-builder";
128
+ import type { MediaFile } from "rte-builder";
129
+
130
+ function App() {
131
+ const handleImagePicker = async (): Promise<MediaFile | null> => {
132
+ // Open your media picker dialog
133
+ const file = await openYourMediaPicker("image");
134
+
135
+ if (file) {
136
+ return {
137
+ url: file.url,
138
+ name: file.name,
139
+ alt: file.name,
140
+ };
141
+ }
142
+ return null;
143
+ };
144
+
145
+ const handleVideoPicker = async (): Promise<MediaFile | null> => {
146
+ const file = await openYourMediaPicker("video");
147
+ return file ? { url: file.url, name: file.name } : null;
148
+ };
149
+
150
+ return (
151
+ <RichTextEditor
152
+ value={content}
153
+ onChange={setContent}
154
+ onMediaPickerImage={handleImagePicker}
155
+ onMediaPickerVideo={handleVideoPicker}
156
+ />
157
+ );
158
+ }
159
+ ```
160
+
161
+ ## API Reference
162
+
163
+ ### Component Props
164
+
165
+ | Prop | Type | Default | Description |
166
+ | --------------------- | ---------------------------------- | ------------------- | ------------------------------- |
167
+ | `value` | `string` | `''` | HTML content |
168
+ | `onChange` | `(content: string) => void` | - | Content change handler |
169
+ | `onBlur` | `() => void` | - | Blur event handler |
170
+ | `onFocus` | `() => void` | - | Focus event handler |
171
+ | `placeholder` | `string` | `'Start typing...'` | Placeholder text |
172
+ | `height` | `number` | `400` | Editor height in pixels |
173
+ | `minHeight` | `number` | `300` | Minimum height |
174
+ | `maxHeight` | `number` | - | Maximum height |
175
+ | `disabled` | `boolean` | `false` | Disable editing |
176
+ | `readOnly` | `boolean` | `false` | Read-only mode |
177
+ | `charCounterMax` | `number` | `-1` | Character limit (-1 = no limit) |
178
+ | `showCharCounter` | `boolean` | `false` | Show character count |
179
+ | `toolbarPreset` | `'full' \| 'medium' \| 'simple'` | `'full'` | Toolbar preset |
180
+ | `toolbarButtons` | `ToolbarButton[]` | - | Custom toolbar buttons |
181
+ | `className` | `string` | `''` | Additional CSS class |
182
+ | `onMediaPickerImage` | `() => Promise<MediaFile \| null>` | - | Image picker callback |
183
+ | `onMediaPickerVideo` | `() => Promise<MediaFile \| null>` | - | Video picker callback |
184
+ | `enableCodeHighlight` | `boolean` | `true` | Enable syntax highlighting |
185
+ | `defaultCodeLanguage` | `string` | `'javascript'` | Default code language |
186
+
187
+ ### Ref Methods
188
+
189
+ ```tsx
190
+ const editorRef = useRef<EditorRef>(null);
191
+
192
+ // Get content
193
+ const html = editorRef.current?.getContent();
194
+ const text = editorRef.current?.getText();
195
+ const json = editorRef.current?.getJSON();
196
+
197
+ // Set content
198
+ editorRef.current?.setContent("<p>Hello World</p>");
199
+
200
+ // Navigation
201
+ editorRef.current?.focus();
202
+ editorRef.current?.blur();
203
+
204
+ // Insert
205
+ editorRef.current?.insertHTML("<strong>Bold text</strong>");
206
+ editorRef.current?.insertText("Plain text");
207
+
208
+ // Clear
209
+ editorRef.current?.clear();
210
+
211
+ // State
212
+ const empty = editorRef.current?.isEmpty();
213
+ const chars = editorRef.current?.getCharacterCount();
214
+ const words = editorRef.current?.getWordCount();
215
+
216
+ // History
217
+ editorRef.current?.undo();
218
+ editorRef.current?.redo();
219
+ const canUndo = editorRef.current?.canUndo();
220
+ const canRedo = editorRef.current?.canRedo();
221
+
222
+ // Actions
223
+ editorRef.current?.toggleFullscreen();
224
+ editorRef.current?.print();
225
+
226
+ // Native editor access
227
+ const tiptapEditor = editorRef.current?.getNativeEditor();
228
+ ```
229
+
230
+ ### Toolbar Buttons
231
+
232
+ All available toolbar buttons:
233
+
234
+ **Text Formatting:**
235
+ `bold`, `italic`, `underline`, `strike`, `code`, `codeBlock`, `subscript`, `superscript`, `clearFormatting`
236
+
237
+ **Font & Colors:**
238
+ `fontFamily`, `fontSize`, `lineHeight`, `textColor`, `backgroundColor`
239
+
240
+ **Alignment & Indentation:**
241
+ `alignLeft`, `alignCenter`, `alignRight`, `alignJustify`, `indent`, `outdent`
242
+
243
+ **Lists:**
244
+ `bulletList`, `orderedList`
245
+
246
+ **Headings:**
247
+ `heading1`, `heading2`, `heading3`, `heading4`, `heading5`, `heading6`
248
+
249
+ **Blocks:**
250
+ `blockquote`, `horizontalRule`
251
+
252
+ **Links & Media:**
253
+ `link`, `unlink`, `image`, `video`, `table`, `emoji`
254
+
255
+ **Actions:**
256
+ `undo`, `redo`, `fullscreen`, `print`
257
+
258
+ **Special:**
259
+ `separator`
260
+
261
+ ### Toolbar Presets
262
+
263
+ ```tsx
264
+ import { toolbarPresets, getToolbarPreset } from "rte-builder";
265
+
266
+ // Available presets
267
+ const full = getToolbarPreset("full"); // All features (50+ buttons)
268
+ const medium = getToolbarPreset("medium"); // Standard features (30+ buttons)
269
+ const simple = getToolbarPreset("simple"); // Basic features (12 buttons)
270
+ const minimal = getToolbarPreset("minimal"); // Just essentials (7 buttons)
271
+ const code = getToolbarPreset("code"); // For technical docs
272
+ const blog = getToolbarPreset("blog"); // For blog posts
273
+ const email = getToolbarPreset("email"); // For email composition
274
+ ```
275
+
276
+ ## Editor Registry
277
+
278
+ Register custom editors or check availability:
279
+
280
+ ```tsx
281
+ import {
282
+ EditorRegistry,
283
+ registerAdapter,
284
+ isEditorAvailable,
285
+ getAvailableAdapters,
286
+ getEditorFeatures,
287
+ } from "rte-builder";
288
+
289
+ // Check what's available
290
+ const available = getAvailableAdapters();
291
+ console.log(available.map((a) => a.name));
292
+
293
+ // Check specific editor
294
+ if (isEditorAvailable("tiptap")) {
295
+ console.log("TipTap is ready!");
296
+ }
297
+
298
+ // Get feature comparison
299
+ const features = getEditorFeatures("tiptap");
300
+ console.log(features.tables); // true
301
+ console.log(features.collaboration); // false
302
+ ```
303
+
304
+ ## Custom Extensions (TipTap)
305
+
306
+ The library exports TipTap extensions for advanced use:
307
+
308
+ ```tsx
309
+ import {
310
+ FontSize,
311
+ LineHeight,
312
+ Video,
313
+ Emoji,
314
+ Fullscreen,
315
+ Print,
316
+ Indent,
317
+ EMOJI_CATEGORIES,
318
+ } from "rte-builder";
319
+
320
+ // Use with TipTap directly
321
+ import { useEditor } from "@tiptap/react";
322
+
323
+ const editor = useEditor({
324
+ extensions: [
325
+ // ... other extensions
326
+ FontSize,
327
+ LineHeight,
328
+ Fullscreen,
329
+ ],
330
+ });
331
+ ```
332
+
333
+ ## Styling
334
+
335
+ The library includes comprehensive CSS. You can customize via CSS variables:
336
+
337
+ ```css
338
+ /* Override in your CSS */
339
+ .rte-builder-wrapper {
340
+ --editor-border-color: #e5e7eb;
341
+ --editor-background: #ffffff;
342
+ --toolbar-background: #f9fafb;
343
+ --button-active-color: #3b82f6;
344
+ --text-color: #1f2937;
345
+ }
346
+
347
+ /* Or use custom classes */
348
+ .my-editor .rte-builder-toolbar {
349
+ background: #1a1a1a;
350
+ }
351
+ ```
352
+
353
+ ## Project Structure
354
+
355
+ ```
356
+ rte-builder/
357
+ ├── src/
358
+ │ ├── core/ # Core types, registry, presets
359
+ │ │ ├── types.ts # Unified type definitions
360
+ │ │ ├── registry.ts # Editor adapter registry
361
+ │ │ └── presets.ts # Toolbar presets
362
+ │ ├── adapters/ # Editor implementations
363
+ │ │ ├── tiptap/ # TipTap adapter (included)
364
+ │ │ ├── slate/ # Slate.js adapter (included)
365
+ │ │ └── lexical/ # Lexical adapter (included)
366
+ │ ├── components/ # React components
367
+ │ │ ├── RichTextEditor.tsx # Legacy TipTap component
368
+ │ │ └── UnifiedEditor.tsx # New unified component
369
+ │ ├── extensions/ # Custom TipTap extensions
370
+ │ └── styles/ # CSS styles
371
+ ├── dist/ # Built output
372
+ ├── README.md
373
+ └── package.json
374
+ ```
375
+
376
+ ## Roadmap
377
+
378
+ - [x] **v1.0**: Complete TipTap implementation
379
+ - [x] **v1.1**: Generic adapter architecture
380
+ - [x] **v1.2**: Slate.js adapter
381
+ - [x] **v1.3**: Lexical adapter
382
+ - [x] **v2.0**: Collaborative editing
383
+ - [x] **v2.1**: Comments & annotations
384
+ - [x] **v2.2**: Version history
385
+ - [ ] **v2.3**: Quill adapter
386
+ - [ ] **v2.4**: Draft.js adapter
387
+
388
+ ## Collaborative Editing (v2.0)
389
+
390
+ Enable real-time collaboration with presence indicators:
391
+
392
+ ```tsx
393
+ import { UnifiedEditor, CollaborationProvider, PresenceIndicator } from 'rte-builder'
394
+
395
+ function CollaborativeEditor() {
396
+ return (
397
+ <CollaborationProvider
398
+ config={{
399
+ provider: 'websocket',
400
+ serverUrl: 'wss://your-server.com/collab',
401
+ roomId: 'document-123',
402
+ user: {
403
+ id: 'user-1',
404
+ name: 'John Doe',
405
+ color: '#3b82f6',
406
+ },
407
+ }}
408
+ onStatusChange={(status) => console.log('Status:', status)}
409
+ onUsersChange={(users) => console.log('Users:', users)}
410
+ >
411
+ <PresenceIndicator />
412
+ <UnifiedEditor
413
+ value={content}
414
+ onChange={setContent}
415
+ />
416
+ </CollaborationProvider>
417
+ )
418
+ }
419
+ ```
420
+
421
+ ## Comments & Annotations (v2.1)
422
+
423
+ Add inline comments and annotations to your documents:
424
+
425
+ ```tsx
426
+ import { UnifiedEditor, CommentsProvider, CommentsPanel } from 'rte-builder'
427
+
428
+ function EditorWithComments() {
429
+ return (
430
+ <CommentsProvider
431
+ config={{
432
+ currentUser: {
433
+ id: 'user-1',
434
+ name: 'John Doe',
435
+ },
436
+ allowResolve: true,
437
+ allowReactions: true,
438
+ }}
439
+ onThreadsChange={(threads) => saveThreads(threads)}
440
+ >
441
+ <div style={{ display: 'flex' }}>
442
+ <UnifiedEditor
443
+ value={content}
444
+ onChange={setContent}
445
+ />
446
+ <CommentsPanel position="right" />
447
+ </div>
448
+ </CommentsProvider>
449
+ )
450
+ }
451
+ ```
452
+
453
+ ## Version History (v2.2)
454
+
455
+ Track and restore document versions:
456
+
457
+ ```tsx
458
+ import { UnifiedEditor, VersionHistoryProvider, VersionHistoryPanel } from 'rte-builder'
459
+
460
+ function EditorWithHistory() {
461
+ const editorRef = useRef(null)
462
+
463
+ return (
464
+ <VersionHistoryProvider
465
+ config={{
466
+ currentUser: {
467
+ id: 'user-1',
468
+ name: 'John Doe',
469
+ },
470
+ autoSave: true,
471
+ autoSaveInterval: 60000, // 1 minute
472
+ maxVersions: 100,
473
+ onRestore: (version) => {
474
+ editorRef.current?.setContent(version.content)
475
+ },
476
+ }}
477
+ getCurrentContent={() => ({
478
+ html: editorRef.current?.getContent() || '',
479
+ text: editorRef.current?.getText() || '',
480
+ })}
481
+ >
482
+ <div style={{ display: 'flex' }}>
483
+ <UnifiedEditor
484
+ ref={editorRef}
485
+ value={content}
486
+ onChange={setContent}
487
+ />
488
+ <VersionHistoryPanel position="right" />
489
+ </div>
490
+ </VersionHistoryProvider>
491
+ )
492
+ }
493
+ ```
494
+
495
+ ## License
496
+
497
+ MIT License - Free for commercial and personal use.
498
+
499
+ ## Contributing
500
+
501
+ Contributions welcome! Please read our contributing guidelines.
502
+
503
+ ## Support
504
+
505
+ - GitHub Issues: Report bugs or request features