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 +21 -0
- package/README.md +418 -0
- package/dist/index.css +580 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +690 -0
- package/dist/index.d.ts +690 -0
- package/dist/index.js +8717 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8715 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +121 -0
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)
|