rte-builder 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RTE Builder Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,418 @@
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', 'italic', 'underline',
97
+ 'separator',
98
+ 'heading1', 'heading2',
99
+ 'separator',
100
+ 'bulletList', 'orderedList',
101
+ 'separator',
102
+ 'link', 'image',
103
+ 'separator',
104
+ 'undo', 'redo',
105
+ ]
106
+
107
+ function App() {
108
+ return (
109
+ <RichTextEditor
110
+ value={content}
111
+ onChange={setContent}
112
+ toolbarButtons={myToolbar}
113
+ />
114
+ )
115
+ }
116
+ ```
117
+
118
+ ### With Media Picker Integration
119
+
120
+ ```tsx
121
+ import { RichTextEditor } from 'rte-builder'
122
+ import type { MediaFile } from 'rte-builder'
123
+
124
+ function App() {
125
+ const handleImagePicker = async (): Promise<MediaFile | null> => {
126
+ // Open your media picker dialog
127
+ const file = await openYourMediaPicker('image')
128
+
129
+ if (file) {
130
+ return {
131
+ url: file.url,
132
+ name: file.name,
133
+ alt: file.name,
134
+ }
135
+ }
136
+ return null
137
+ }
138
+
139
+ const handleVideoPicker = async (): Promise<MediaFile | null> => {
140
+ const file = await openYourMediaPicker('video')
141
+ return file ? { url: file.url, name: file.name } : null
142
+ }
143
+
144
+ return (
145
+ <RichTextEditor
146
+ value={content}
147
+ onChange={setContent}
148
+ onMediaPickerImage={handleImagePicker}
149
+ onMediaPickerVideo={handleVideoPicker}
150
+ />
151
+ )
152
+ }
153
+ ```
154
+
155
+ ## API Reference
156
+
157
+ ### Component Props
158
+
159
+ | Prop | Type | Default | Description |
160
+ |------|------|---------|-------------|
161
+ | `value` | `string` | `''` | HTML content |
162
+ | `onChange` | `(content: string) => void` | - | Content change handler |
163
+ | `onBlur` | `() => void` | - | Blur event handler |
164
+ | `onFocus` | `() => void` | - | Focus event handler |
165
+ | `placeholder` | `string` | `'Start typing...'` | Placeholder text |
166
+ | `height` | `number` | `400` | Editor height in pixels |
167
+ | `minHeight` | `number` | `300` | Minimum height |
168
+ | `maxHeight` | `number` | - | Maximum height |
169
+ | `disabled` | `boolean` | `false` | Disable editing |
170
+ | `readOnly` | `boolean` | `false` | Read-only mode |
171
+ | `charCounterMax` | `number` | `-1` | Character limit (-1 = no limit) |
172
+ | `showCharCounter` | `boolean` | `false` | Show character count |
173
+ | `toolbarPreset` | `'full' \| 'medium' \| 'simple'` | `'full'` | Toolbar preset |
174
+ | `toolbarButtons` | `ToolbarButton[]` | - | Custom toolbar buttons |
175
+ | `className` | `string` | `''` | Additional CSS class |
176
+ | `onMediaPickerImage` | `() => Promise<MediaFile \| null>` | - | Image picker callback |
177
+ | `onMediaPickerVideo` | `() => Promise<MediaFile \| null>` | - | Video picker callback |
178
+ | `enableCodeHighlight` | `boolean` | `true` | Enable syntax highlighting |
179
+ | `defaultCodeLanguage` | `string` | `'javascript'` | Default code language |
180
+
181
+ ### Ref Methods
182
+
183
+ ```tsx
184
+ const editorRef = useRef<EditorRef>(null)
185
+
186
+ // Get content
187
+ const html = editorRef.current?.getContent()
188
+ const text = editorRef.current?.getText()
189
+ const json = editorRef.current?.getJSON()
190
+
191
+ // Set content
192
+ editorRef.current?.setContent('<p>Hello World</p>')
193
+
194
+ // Navigation
195
+ editorRef.current?.focus()
196
+ editorRef.current?.blur()
197
+
198
+ // Insert
199
+ editorRef.current?.insertHTML('<strong>Bold text</strong>')
200
+ editorRef.current?.insertText('Plain text')
201
+
202
+ // Clear
203
+ editorRef.current?.clear()
204
+
205
+ // State
206
+ const empty = editorRef.current?.isEmpty()
207
+ const chars = editorRef.current?.getCharacterCount()
208
+ const words = editorRef.current?.getWordCount()
209
+
210
+ // History
211
+ editorRef.current?.undo()
212
+ editorRef.current?.redo()
213
+ const canUndo = editorRef.current?.canUndo()
214
+ const canRedo = editorRef.current?.canRedo()
215
+
216
+ // Actions
217
+ editorRef.current?.toggleFullscreen()
218
+ editorRef.current?.print()
219
+
220
+ // Native editor access
221
+ const tiptapEditor = editorRef.current?.getNativeEditor()
222
+ ```
223
+
224
+ ### Toolbar Buttons
225
+
226
+ All available toolbar buttons:
227
+
228
+ **Text Formatting:**
229
+ `bold`, `italic`, `underline`, `strike`, `code`, `codeBlock`, `subscript`, `superscript`, `clearFormatting`
230
+
231
+ **Font & Colors:**
232
+ `fontFamily`, `fontSize`, `lineHeight`, `textColor`, `backgroundColor`
233
+
234
+ **Alignment & Indentation:**
235
+ `alignLeft`, `alignCenter`, `alignRight`, `alignJustify`, `indent`, `outdent`
236
+
237
+ **Lists:**
238
+ `bulletList`, `orderedList`
239
+
240
+ **Headings:**
241
+ `heading1`, `heading2`, `heading3`, `heading4`, `heading5`, `heading6`
242
+
243
+ **Blocks:**
244
+ `blockquote`, `horizontalRule`
245
+
246
+ **Links & Media:**
247
+ `link`, `unlink`, `image`, `video`, `table`, `emoji`
248
+
249
+ **Actions:**
250
+ `undo`, `redo`, `fullscreen`, `print`
251
+
252
+ **Special:**
253
+ `separator`
254
+
255
+ ### Toolbar Presets
256
+
257
+ ```tsx
258
+ import { toolbarPresets, getToolbarPreset } from 'rte-builder'
259
+
260
+ // Available presets
261
+ const full = getToolbarPreset('full') // All features (50+ buttons)
262
+ const medium = getToolbarPreset('medium') // Standard features (30+ buttons)
263
+ const simple = getToolbarPreset('simple') // Basic features (12 buttons)
264
+ const minimal = getToolbarPreset('minimal') // Just essentials (7 buttons)
265
+ const code = getToolbarPreset('code') // For technical docs
266
+ const blog = getToolbarPreset('blog') // For blog posts
267
+ const email = getToolbarPreset('email') // For email composition
268
+ ```
269
+
270
+ ## Editor Registry
271
+
272
+ Register custom editors or check availability:
273
+
274
+ ```tsx
275
+ import {
276
+ EditorRegistry,
277
+ registerAdapter,
278
+ isEditorAvailable,
279
+ getAvailableAdapters,
280
+ getEditorFeatures,
281
+ } from 'rte-builder'
282
+
283
+ // Check what's available
284
+ const available = getAvailableAdapters()
285
+ console.log(available.map(a => a.name))
286
+
287
+ // Check specific editor
288
+ if (isEditorAvailable('tiptap')) {
289
+ console.log('TipTap is ready!')
290
+ }
291
+
292
+ // Get feature comparison
293
+ const features = getEditorFeatures('tiptap')
294
+ console.log(features.tables) // true
295
+ console.log(features.collaboration) // false
296
+ ```
297
+
298
+ ## Custom Extensions (TipTap)
299
+
300
+ The library exports TipTap extensions for advanced use:
301
+
302
+ ```tsx
303
+ import {
304
+ FontSize,
305
+ LineHeight,
306
+ Video,
307
+ Emoji,
308
+ Fullscreen,
309
+ Print,
310
+ Indent,
311
+ EMOJI_CATEGORIES,
312
+ } from 'rte-builder'
313
+
314
+ // Use with TipTap directly
315
+ import { useEditor } from '@tiptap/react'
316
+
317
+ const editor = useEditor({
318
+ extensions: [
319
+ // ... other extensions
320
+ FontSize,
321
+ LineHeight,
322
+ Fullscreen,
323
+ ],
324
+ })
325
+ ```
326
+
327
+ ## Styling
328
+
329
+ The library includes comprehensive CSS. You can customize via CSS variables:
330
+
331
+ ```css
332
+ /* Override in your CSS */
333
+ .rte-builder-wrapper {
334
+ --editor-border-color: #e5e7eb;
335
+ --editor-background: #ffffff;
336
+ --toolbar-background: #f9fafb;
337
+ --button-active-color: #3b82f6;
338
+ --text-color: #1f2937;
339
+ }
340
+
341
+ /* Or use custom classes */
342
+ .my-editor .rte-builder-toolbar {
343
+ background: #1a1a1a;
344
+ }
345
+ ```
346
+
347
+ ## Migration from Froala
348
+
349
+ See [MIGRATION_FROM_FROALA.md](./MIGRATION_FROM_FROALA.md) for a complete migration guide.
350
+
351
+ **Quick comparison:**
352
+
353
+ ```tsx
354
+ // Before (Froala)
355
+ <FroalaEditor
356
+ model={content}
357
+ onModelChange={setContent}
358
+ config={{
359
+ key: FROALA_LICENSE_KEY, // ❌ $399+/year
360
+ placeholderText: 'Type...',
361
+ }}
362
+ />
363
+
364
+ // After (RTE Builder)
365
+ <RichTextEditor
366
+ value={content}
367
+ onChange={setContent}
368
+ placeholder="Type..." // ✅ FREE (MIT)
369
+ />
370
+ ```
371
+
372
+ ## Project Structure
373
+
374
+ ```
375
+ rte-builder/
376
+ ├── src/
377
+ │ ├── core/ # Core types, registry, presets
378
+ │ │ ├── types.ts # Unified type definitions
379
+ │ │ ├── registry.ts # Editor adapter registry
380
+ │ │ └── presets.ts # Toolbar presets
381
+ │ ├── adapters/ # Editor implementations
382
+ │ │ ├── tiptap/ # TipTap adapter (included)
383
+ │ │ ├── slate/ # Slate.js adapter (included)
384
+ │ │ └── lexical/ # Lexical adapter (included)
385
+ │ ├── components/ # React components
386
+ │ │ ├── RichTextEditor.tsx # Legacy TipTap component
387
+ │ │ └── UnifiedEditor.tsx # New unified component
388
+ │ ├── extensions/ # Custom TipTap extensions
389
+ │ └── styles/ # CSS styles
390
+ ├── dist/ # Built output
391
+ ├── README.md
392
+ └── package.json
393
+ ```
394
+
395
+ ## Roadmap
396
+
397
+ - [x] **v1.0**: Complete TipTap implementation
398
+ - [x] **v1.1**: Generic adapter architecture
399
+ - [x] **v1.2**: Slate.js adapter
400
+ - [x] **v1.3**: Lexical adapter
401
+ - [ ] **v2.0**: Collaborative editing
402
+ - [ ] **v2.1**: Comments & annotations
403
+ - [ ] **v2.2**: Version history
404
+ - [ ] **v2.3**: Quill adapter
405
+ - [ ] **v2.4**: Draft.js adapter
406
+
407
+ ## License
408
+
409
+ MIT License - Free for commercial and personal use.
410
+
411
+ ## Contributing
412
+
413
+ Contributions welcome! Please read our contributing guidelines.
414
+
415
+ ## Support
416
+
417
+ - GitHub Issues: Report bugs or request features
418
+ - Documentation: See [EXAMPLES.md](./EXAMPLES.md) and [QUICKSTART.md](./QUICKSTART.md)