@abduljebar/text-editor 2.4.0 → 2.5.2

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,373 +1,565 @@
1
- ```tsx
2
- import '@abduljebar/text-editor/dist/index.css';
3
- import { TextEditor } from "@abduljebar/text-editor";
4
- ```
5
-
6
- # @abduljebar/text-editor
7
-
8
- A modern, feature-rich React text editor component with beautiful styling and extensive customization options. Perfect for blogs, content management systems, and any application requiring rich text editing capabilities.
9
-
10
- ## Features
11
-
12
- ### 🎨 Rich Text Editing
13
- - **Text Formatting**: Bold, italic, underline, strikethrough
14
- - **Color Support**: 20 text colors & 25 background colors with intuitive pickers
15
- - **Headings**: H1, H2, H3 with automatic styling
16
- - **Lists**: Bulleted and numbered lists
17
- - **Block Elements**: Quotes and code blocks with syntax styling
18
- - **Undo/Redo**: Full history support
19
-
20
- ### 🎯 Smart UX
21
- - **Auto-styling**: Automatic application of beautiful Tailwind CSS styles
22
- - **Contextual Toolbar**: Appears only when focused and editable
23
- - **Real-time Stats**: Word and character count in status bar
24
- - **Smart Format Detection**: Visual indicators for active text formats
25
- - **Tab Support**: Indentation with Tab key
26
-
27
- ### 🔧 Flexible Configuration
28
- - **Read-only Mode**: Display content without editing capabilities
29
- - **Customizable Height**: Flexible sizing options
30
- - **Title Support**: Optional document title with real-time updates
31
- - **Action Buttons**: Built-in save and export functionality
32
- - **Event Handling**: Comprehensive callback system
33
-
34
- ### 🚀 Advanced Features
35
- - **React Hook**: `useTextEditor` for custom implementations
36
- - **HTML Export**: Generate complete HTML documents
37
- - **Validation**: Built-in content validation
38
- - **State Management**: Full control over editor state
39
- - **TypeScript**: Fully typed for better development experience
40
-
41
- ## 📦 Installation
42
-
43
- ```bash
44
- npm install @abduljebar/text-editor
45
- # or
46
- yarn add @abduljebar/text-editor
47
- # or
48
- pnpm add @abduljebar/text-editor
49
- ```
50
-
51
- ## 🚀 Quick Start
52
-
53
- ```tsx
54
- import '@abduljebar/text-editor/dist/index.css';
55
- import { TextEditor } from "@abduljebar/text-editor";
56
-
57
- function App() {
58
- return (
59
- <TextEditor
60
- height="min-h-[400px]"
61
- onChange={(content, html, title) => {
62
- console.log("Content:", content);
63
- console.log("HTML:", html);
64
- console.log("Title:", title);
65
- }}
66
- initialContent="<h1>Welcome to Your Document</h1><p>Start editing here...</p>"
67
- />
68
- );
69
- }
70
- ```
71
-
72
- ## 📖 Basic Usage
73
-
74
- ### Simple Implementation
75
-
76
- ```tsx
77
- import '@abduljebar/text-editor/dist/index.css';
78
- import { TextEditor } from "@abduljebar/text-editor";
79
-
80
- function MyEditor() {
81
- const handleSave = (content: string, html: string) => {
82
- // Save to your backend or state management
83
- console.log("Saving:", { content, html });
84
- };
85
-
86
- const handleExport = (html: string) => {
87
- // Export as HTML file
88
- const blob = new Blob([html], { type: 'text/html' });
89
- const url = URL.createObjectURL(blob);
90
- const a = document.createElement('a');
91
- a.href = url;
92
- a.download = 'document.html';
93
- a.click();
94
- };
95
-
96
- return (
97
- <TextEditor
98
- showButtons={true}
99
- showSaveTitle={true}
100
- showStatusBar={true}
101
- onSave={handleSave}
102
- onExport={handleExport}
103
- onChange={(content, html, title) => {
104
- // Real-time updates
105
- console.log("Changes:", { content, html, title });
106
- }}
107
- />
108
- );
109
- }
110
- ```
111
-
112
- ### Read-only Mode
113
-
114
- ```tsx
115
- import '@abduljebar/text-editor/dist/index.css';
116
- import { TextEditor } from "@abduljebar/text-editor";
117
-
118
- function ReadOnlyView() {
119
- return (
120
- <TextEditor
121
- readOnly={true}
122
- initialContent="<h1>Published Article</h1><p>This content cannot be edited.</p>"
123
- showStatusBar={true}
124
- />
125
- );
126
- }
127
- ```
128
-
129
- ## ⚙️ API Reference
130
-
131
- ### TextEditor Props
132
-
133
- | Prop | Type | Default | Description |
134
- |------|------|---------|-------------|
135
- | `initialContent` | `string` | `""` | Initial HTML content for the editor |
136
- | `onChange` | `(content: string, html: string, title?: string) => void` | `undefined` | Callback when content changes |
137
- | `onSave` | `(content: string, html: string) => void` | `undefined` | Callback when save is triggered |
138
- | `onExport` | `(html: string) => void` | `undefined` | Callback when export is triggered |
139
- | `readOnly` | `boolean` | `false` | Disable editing when true |
140
- | `showButtons` | `boolean` | `false` | Show save/export buttons |
141
- | `showSaveTitle` | `boolean` | `false` | Show document title input |
142
- | `showStatusBar` | `boolean` | `false` | Show word/character count |
143
- | `height` | `string` | `"500px"` | Editor height (any CSS value) |
144
-
145
- ### useTextEditor Hook
146
-
147
- For advanced usage and custom implementations:
148
-
149
- ```tsx
150
- import '@abduljebar/text-editor/dist/index.css';
151
- import { useTextEditor } from "@abduljebar/text-editor";
152
-
153
- function CustomEditor() {
154
- const {
155
- editorState,
156
- editorRef,
157
- updateContent,
158
- updateTitle,
159
- executeCommand,
160
- getValidationResult,
161
- exportToHTML,
162
- clearEditor,
163
- resetToInitial,
164
- activeFormats,
165
- isLinkActive,
166
- } = useTextEditor("Initial content", false);
167
-
168
- // Use the state and methods to build custom UI
169
- return (
170
- <div>
171
- <div
172
- ref={editorRef}
173
- contentEditable
174
- onInput={(e) => updateContent(e.currentTarget.innerHTML)}
175
- className="border p-4 min-h-[200px]"
176
- />
177
- <button onClick={() => executeCommand('bold')}>
178
- Bold
179
- </button>
180
- </div>
181
- );
182
- }
183
- ```
184
-
185
- #### Hook Return Values
186
-
187
- | Property | Type | Description |
188
- |----------|------|-------------|
189
- | `editorState` | `object` | Current editor state (content, title, counts) |
190
- | `editorRef` | `RefObject` | Reference to the editable element |
191
- | `updateContent` | `(content: string) => void` | Update editor content |
192
- | `updateTitle` | `(title: string) => void` | Update document title |
193
- | `executeCommand` | `(command: string, value?: string) => void` | Execute formatting commands |
194
- | `getValidationResult` | `() => ValidationResult` | Validate and get editor data |
195
- | `exportToHTML` | `(options?) => string` | Generate HTML export |
196
- | `clearEditor` | `() => void` | Clear all content |
197
- | `resetToInitial` | `() => void` | Reset to initial content |
198
- | `activeFormats` | `object` | Current active text formats |
199
- | `isLinkActive` | `boolean` | Whether a link is currently selected |
200
-
201
- ## 🎨 Styling & Customization
202
-
203
- ### Default Styling
204
-
205
- The editor comes with beautiful default styling using Tailwind CSS classes:
206
-
207
- - **Headings**: Proper hierarchy with borders and spacing
208
- - **Paragraphs**: Optimal line height and margins
209
- - **Lists**: Clean indentation and spacing
210
- - **Code Blocks**: Dark theme with proper monospace fonts
211
- - **Quotes**: Elegant bordered design
212
- - **Links**: Blue color with hover effects
213
-
214
- ### Custom Styling
215
-
216
- You can override the default styles by targeting the editor's CSS classes or using the `className` prop:
217
-
218
- ```tsx
219
- import '@abduljebar/text-editor/dist/index.css';
220
- import { TextEditor } from "@abduljebar/text-editor";
221
-
222
- <TextEditor
223
- className="custom-editor-styles"
224
- // ... other props
225
- />
226
- ```
227
-
228
- ```css
229
- .custom-editor-styles {
230
- /* Your custom styles */
231
- }
232
-
233
- .custom-editor-styles h1 {
234
- /* Custom heading styles */
235
- }
236
- ```
237
-
238
- ## 🔧 Advanced Examples
239
-
240
- ### Integration with Form Libraries
241
-
242
- ```tsx
243
- import '@abduljebar/text-editor/dist/index.css';
244
- import { useForm } from 'react-hook-form';
245
- import { TextEditor } from "@abduljebar/text-editor";
246
-
247
- function ArticleForm() {
248
- const { register, handleSubmit, setValue, watch } = useForm();
249
-
250
- const handleEditorChange = (content: string, html: string, title?: string) => {
251
- setValue('content', html);
252
- setValue('title', title);
253
- };
254
-
255
- return (
256
- <form onSubmit={handleSubmit(data => console.log(data))}>
257
- <TextEditor
258
- showSaveTitle={true}
259
- showButtons={true}
260
- onChange={handleEditorChange}
261
- onSave={(content, html) => {
262
- // Handle form submission
263
- handleSubmit(data => console.log(data))();
264
- }}
265
- />
266
- </form>
267
- );
268
- }
269
- ```
270
-
271
- ### Custom Toolbar Implementation
272
-
273
- ```tsx
274
- import '@abduljebar/text-editor/dist/index.css';
275
- import { useTextEditor } from "@abduljebar/text-editor";
276
-
277
- function CustomToolbarEditor() {
278
- const { executeCommand, activeFormats, editorRef } = useTextEditor();
279
-
280
- return (
281
- <div className="editor-container">
282
- <div className="custom-toolbar">
283
- <button
284
- onClick={() => executeCommand('bold')}
285
- className={activeFormats.bold ? 'active' : ''}
286
- >
287
- B
288
- </button>
289
- <button
290
- onClick={() => executeCommand('italic')}
291
- className={activeFormats.italic ? 'active' : ''}
292
- >
293
- I
294
- </button>
295
- {/* Add more custom buttons */}
296
- </div>
297
- <div
298
- ref={editorRef}
299
- contentEditable
300
- className="editor-content"
301
- />
302
- </div>
303
- );
304
- }
305
- ```
306
-
307
- ## 🌈 Color Palettes
308
-
309
- ### Text Colors (20 colors)
310
- - Basic: Black, White
311
- - Primary: Red, Green, Blue
312
- - Secondary: Yellow, Magenta, Cyan, Orange, Purple
313
- - Additional: Dark Green, Maroon, Teal, Navy, Gray, Brown, Pink, Gold, Light Green, Light Blue
314
-
315
- ### Background Colors (25 colors)
316
- - Same as text colors plus light variants
317
- - Light variants: Misty Rose, Honeydew, Alice Blue, Lemon Chiffon, White Smoke, Lavender, and more
318
-
319
- ## 📋 Browser Support
320
-
321
- - Chrome 60+
322
- - Firefox 55+
323
- - Safari 12+
324
- - Edge 79+
325
-
326
- ## 🔒 Accessibility
327
-
328
- - Keyboard navigation support
329
- - ARIA labels for toolbar buttons
330
- - Focus management
331
- - Screen reader compatible
332
-
333
- ## 🐛 Troubleshooting
334
-
335
- ### Common Issues
336
-
337
- 1. **Content not updating**: Ensure you're using the `onChange` callback properly
338
- 2. **Styles not applying**: Make sure Tailwind CSS is properly configured in your project
339
- 3. **Toolbar not appearing**: Check that `readOnly` is set to `false` and the editor is focused
340
-
341
- ### Performance Tips
342
-
343
- - Use `React.memo` if embedding in frequently re-rendering components
344
- - Debounce `onChange` callbacks for heavy operations
345
- - Consider using the hook version for complex custom implementations
346
-
347
- ## 🤝 Contributing
348
-
349
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
350
-
351
- ## 📄 License
352
-
353
- MIT License - see the [LICENSE](LICENSE) file for details.
354
-
355
- ## 🆘 Support
356
-
357
- If you encounter any issues or have questions:
358
-
359
- 1. Check the [documentation](#)
360
- 2. Search [existing issues](https://github.com/abduljebar/text-editor/issues)
361
- 3. Create a [new issue](https://github.com/abduljebar/text-editor/issues/new)
362
-
363
- ## 🚀 Changelog
364
-
365
- ### v1.0.0
366
- - Initial release with core editing features
367
- - Comprehensive text formatting options
368
- - Color support and styling system
369
- - React hook for advanced usage
370
-
371
- ---
372
-
373
- Built with ❤️ by [AbdulJebar Sani](https://github.com/abduljebar49)
1
+ # @abduljebar/text-editor
2
+
3
+ A modern, feature-rich React text editor component with beautiful styling and extensive customization options. Perfect for blogs, content management systems, and any application requiring rich text editing capabilities.
4
+
5
+ ## ✨ Features
6
+
7
+ ### 🎨 Rich Text Editing
8
+ - **Text Formatting**: Bold, italic, underline, strikethrough
9
+ - **Headings**: H1, H2 with automatic styling
10
+ - **Lists**: Bulleted and numbered lists
11
+ - **Alignment**: Left, center, right alignment
12
+ - **Block Elements**: Quotes and code blocks
13
+ - **Undo/Redo**: Full history support
14
+ - **Additional Formatting**: Superscript, subscript, indentation
15
+
16
+ ### 📁 File Management
17
+ - **Image Upload**: Drag & drop, paste, or file picker
18
+ - **Image Validation**: File type and size validation
19
+ - **Pending Images**: Track and upload pending images
20
+ - **HTML Export**: Generate complete HTML documents with styling
21
+ - **Auto-save**: Debounced content changes with configurable delay
22
+
23
+ ### 🎯 Smart UX
24
+ - **Contextual Toolbar**: Appears only when focused and editable
25
+ - **Real-time Stats**: Word and character count in status bar
26
+ - **Smart Format Detection**: Visual indicators for active text formats
27
+ - **Keyboard Shortcuts**: Ctrl+S (save), Ctrl+E (export)
28
+ - **Auto-focus**: Automatic focus on load
29
+ - **Placeholder Support**: Visual placeholder when empty
30
+
31
+ ### 🔧 Flexible Configuration
32
+ - **Read-only Mode**: Display content without editing capabilities
33
+ - **Customizable Height**: Flexible sizing options
34
+ - **Title Support**: Optional document title with real-time updates
35
+ - **Action Buttons**: Built-in save and export functionality
36
+ - **Event Handling**: Comprehensive callback system
37
+ - **Debounce Control**: Configurable change debouncing
38
+
39
+ ### 🚀 Advanced Features
40
+ - **React Hook**: `useTextEditor` for custom implementations
41
+ - **Ref API**: Exposed methods for programmatic control
42
+ - **Selection Management**: Proper cursor and selection handling
43
+ - **Paste/Upload Handling**: Smart image and content paste handling
44
+ - **TypeScript**: Fully typed for better development experience
45
+ - **Validation**: Built-in content validation
46
+
47
+ ## 📦 Installation
48
+
49
+ ```bash
50
+ npm install @abduljebar/text-editor
51
+ # or
52
+ yarn add @abduljebar/text-editor
53
+ # or
54
+ pnpm add @abduljebar/text-editor
55
+ ```
56
+
57
+ ## 🚀 Quick Start
58
+
59
+ ```tsx
60
+ import '@abduljebar/text-editor/dist/index.css';
61
+ import { TextEditor } from "@abduljebar/text-editor";
62
+
63
+ function App() {
64
+ return (
65
+ <TextEditor
66
+ height="500px"
67
+ onChange={(content, html, title) => {
68
+ console.log("Content:", content);
69
+ console.log("HTML:", html);
70
+ console.log("Title:", title);
71
+ }}
72
+ initialContent="<h1>Welcome to Your Document</h1><p>Start editing here...</p>"
73
+ />
74
+ );
75
+ }
76
+ ```
77
+
78
+ ## 📖 Basic Usage
79
+
80
+ ### Simple Implementation
81
+
82
+ ```tsx
83
+ import '@abduljebar/text-editor/dist/index.css';
84
+ import { TextEditor } from "@abduljebar/text-editor";
85
+
86
+ function MyEditor() {
87
+ const handleSave = (content: string, html: string) => {
88
+ // Save to your backend or state management
89
+ console.log("Saving:", { content, html });
90
+ };
91
+
92
+ const handleExport = (html: string) => {
93
+ // Export as HTML file
94
+ const blob = new Blob([html], { type: 'text/html' });
95
+ const url = URL.createObjectURL(blob);
96
+ const a = document.createElement('a');
97
+ a.href = url;
98
+ a.download = 'document.html';
99
+ a.click();
100
+ };
101
+
102
+ return (
103
+ <TextEditor
104
+ showButtons={true}
105
+ showSaveTitle={true}
106
+ showStatusBar={true}
107
+ onSave={handleSave}
108
+ onExport={handleExport}
109
+ onChange={(content, html, title) => {
110
+ // Real-time updates
111
+ console.log("Changes:", { content, html, title });
112
+ }}
113
+ />
114
+ );
115
+ }
116
+ ```
117
+
118
+ ### Read-only Mode
119
+
120
+ ```tsx
121
+ import '@abduljebar/text-editor/dist/index.css';
122
+ import { TextEditor } from "@abduljebar/text-editor";
123
+
124
+ function ReadOnlyView() {
125
+ return (
126
+ <TextEditor
127
+ readOnly={true}
128
+ initialContent="<h1>Published Article</h1><p>This content cannot be edited.</p>"
129
+ showStatusBar={true}
130
+ />
131
+ );
132
+ }
133
+ ```
134
+
135
+ ### With Image Upload
136
+
137
+ ```tsx
138
+ import '@abduljebar/text-editor/dist/index.css';
139
+ import { TextEditor } from "@abduljebar/text-editor";
140
+
141
+ function EditorWithImages() {
142
+ const handleImageUpload = async (file: File) => {
143
+ // Upload to your backend
144
+ const formData = new FormData();
145
+ formData.append('image', file);
146
+
147
+ const response = await fetch('/api/upload', {
148
+ method: 'POST',
149
+ body: formData,
150
+ });
151
+
152
+ const data = await response.json();
153
+ return data.url; // Return the uploaded image URL
154
+ };
155
+
156
+ return (
157
+ <TextEditor
158
+ showButtons={true}
159
+ onImageUpload={handleImageUpload}
160
+ allowedImageTypes={['image/jpeg', 'image/png', 'image/webp']}
161
+ maxImageSize={10 * 1024 * 1024} // 10MB
162
+ />
163
+ );
164
+ }
165
+ ```
166
+
167
+ ## ⚙️ API Reference
168
+
169
+ ### TextEditor Props
170
+
171
+ | Prop | Type | Default | Description |
172
+ |------|------|---------|-------------|
173
+ | `initialContent` | `string` | `""` | Initial HTML content for the editor |
174
+ | `onChange` | `(content: string, html: string, title?: string) => void` | `undefined` | Callback when content changes |
175
+ | `onSave` | `(content: string, html: string) => void` | `undefined` | Callback when save is triggered |
176
+ | `onExport` | `(html: string) => void` | `undefined` | Callback when export is triggered |
177
+ | `onImageUpload` | `(file: File) => Promise<string>` | `undefined` | Custom image upload handler |
178
+ | `imageUploadEndpoint` | `string` | `undefined` | Endpoint for default image upload |
179
+ | `readOnly` | `boolean` | `false` | Disable editing when true |
180
+ | `showButtons` | `boolean` | `false` | Show save/export buttons |
181
+ | `showSaveTitle` | `boolean` | `false` | Show document title input |
182
+ | `showStatusBar` | `boolean` | `false` | Show word/character count |
183
+ | `height` | `string` | `"500px"` | Editor height (any CSS value) |
184
+ | `allowedImageTypes` | `string[]` | `["image/jpeg","image/png","image/gif","image/webp"]` | Allowed image MIME types |
185
+ | `maxImageSize` | `number` | `5242880` (5MB) | Maximum image size in bytes |
186
+ | `debounceDelay` | `number` | `300` | Debounce delay for onChange in ms |
187
+ | `className` | `string` | `""` | Additional CSS class name |
188
+ | `placeholder` | `string` | `"Start typing here..."` | Placeholder text when empty |
189
+ | `autoFocus` | `boolean` | `false` | Auto-focus editor on load |
190
+ | `onInit` | `(editor: HTMLDivElement) => void` | `undefined` | Callback after editor initialization |
191
+
192
+ ### TextEditor Ref API
193
+
194
+ The component exposes a ref with the following methods:
195
+
196
+ ```typescript
197
+ interface TextEditorRef {
198
+ getContent: () => string;
199
+ getHTML: () => string;
200
+ getTitle: () => string;
201
+ clear: () => void;
202
+ focus: () => void;
203
+ insertText: (text: string) => void;
204
+ insertHTML: (html: string) => void;
205
+ executeCommand: (command: string, value?: string) => void;
206
+ }
207
+ ```
208
+
209
+ Example usage:
210
+ ```tsx
211
+ import { useRef } from 'react';
212
+ import { TextEditor, TextEditorRef } from "@abduljebar/text-editor";
213
+
214
+ function EditorWithRef() {
215
+ const editorRef = useRef<TextEditorRef>(null);
216
+
217
+ const handleGetContent = () => {
218
+ if (editorRef.current) {
219
+ const content = editorRef.current.getContent();
220
+ const html = editorRef.current.getHTML();
221
+ console.log({ content, html });
222
+ }
223
+ };
224
+
225
+ return (
226
+ <>
227
+ <TextEditor ref={editorRef} />
228
+ <button onClick={handleGetContent}>Get Content</button>
229
+ </>
230
+ );
231
+ }
232
+ ```
233
+
234
+ ### useTextEditor Hook
235
+
236
+ For advanced usage and custom implementations:
237
+
238
+ ```tsx
239
+ import '@abduljebar/text-editor/dist/index.css';
240
+ import { useTextEditor } from "@abduljebar/text-editor";
241
+
242
+ function CustomEditor() {
243
+ const {
244
+ editorState,
245
+ editorRef,
246
+ updateContent,
247
+ updateTitle,
248
+ executeCommand,
249
+ getValidationResult,
250
+ exportToHTML,
251
+ clearEditor,
252
+ handlePaste,
253
+ handleDrop,
254
+ insertImage,
255
+ uploadPendingImages,
256
+ } = useTextEditor({
257
+ initialContent: "Initial content",
258
+ onImageUpload: async (file) => {
259
+ // Custom upload logic
260
+ return "https://example.com/image.jpg";
261
+ },
262
+ allowedImageTypes: ["image/jpeg", "image/png"],
263
+ maxImageSize: 10 * 1024 * 1024,
264
+ });
265
+
266
+ return (
267
+ <div>
268
+ <div
269
+ ref={editorRef}
270
+ contentEditable
271
+ onInput={(e) => updateContent(e.currentTarget.innerHTML)}
272
+ className="border p-4 min-h-[200px]"
273
+ onPaste={handlePaste}
274
+ onDrop={handleDrop}
275
+ />
276
+ <button onClick={() => executeCommand('bold')}>
277
+ Bold
278
+ </button>
279
+ <button onClick={() => insertImage(someFile)}>
280
+ Insert Image
281
+ </button>
282
+ </div>
283
+ );
284
+ }
285
+ ```
286
+
287
+ #### Hook Parameters
288
+
289
+ | Parameter | Type | Default | Description |
290
+ |-----------|------|---------|-------------|
291
+ | `initialContent` | `string` | `""` | Initial HTML content |
292
+ | `onImageUpload` | `(file: File) => Promise<string>` | `undefined` | Custom image upload handler |
293
+ | `imageUploadEndpoint` | `string` | `undefined` | Endpoint for default image upload |
294
+ | `allowedImageTypes` | `string[]` | `["image/jpeg","image/png","image/gif","image/webp"]` | Allowed image types |
295
+ | `maxImageSize` | `number` | `5242880` | Max image size in bytes |
296
+
297
+ #### Hook Return Values
298
+
299
+ | Property | Type | Description |
300
+ |----------|------|-------------|
301
+ | `editorState` | `object` | Current editor state with content, title, counts, pending images |
302
+ | `editorRef` | `RefObject<HTMLDivElement>` | Reference to the editable element |
303
+ | `updateContent` | `(content: string) => void` | Update editor content |
304
+ | `updateTitle` | `(title: string) => void` | Update document title |
305
+ | `executeCommand` | `(command: string, value?: string) => void` | Execute formatting commands |
306
+ | `getValidationResult` | `() => ValidationResult` | Validate and get editor data |
307
+ | `exportToHTML` | `(options?) => string` | Generate HTML export |
308
+ | `clearEditor` | `() => void` | Clear all content |
309
+ | `handlePaste` | `(e: React.ClipboardEvent) => void` | Handle paste events |
310
+ | `handleDrop` | `(e: React.DragEvent) => void` | Handle drop events |
311
+ | `insertImage` | `(file: File, atCursor?: boolean) => Promise<void>` | Insert image into editor |
312
+ | `uploadPendingImages` | `() => Promise<void>` | Upload all pending images |
313
+
314
+ ## 🎨 Styling & Customization
315
+
316
+ ### Default Styling
317
+
318
+ The editor comes with beautiful default styling:
319
+
320
+ - **Headings**: Proper hierarchy with appropriate sizing
321
+ - **Paragraphs**: Optimal line height and margins
322
+ - **Lists**: Clean indentation and spacing
323
+ - **Code Blocks**: Proper monospace fonts
324
+ - **Quotes**: Elegant bordered design
325
+ - **Links**: Proper styling with hover effects
326
+ - **Images**: Responsive with rounded corners
327
+
328
+ ### Custom Styling
329
+
330
+ You can override the default styles by targeting the editor's CSS classes or using the `className` prop:
331
+
332
+ ```tsx
333
+ import '@abduljebar/text-editor/dist/index.css';
334
+ import { TextEditor } from "@abduljebar/text-editor";
335
+
336
+ <TextEditor
337
+ className="my-custom-editor"
338
+ // ... other props
339
+ />
340
+ ```
341
+
342
+ ```css
343
+ .my-custom-editor {
344
+ border: 2px solid #4f46e5;
345
+ border-radius: 12px;
346
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
347
+ }
348
+
349
+ .my-custom-editor h1 {
350
+ color: #4f46e5;
351
+ border-bottom: 2px solid #e0e7ff;
352
+ }
353
+
354
+ .my-custom-editor .toolbar {
355
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
356
+ }
357
+ ```
358
+
359
+ ## 🔧 Advanced Examples
360
+
361
+ ### Integration with Form Libraries
362
+
363
+ ```tsx
364
+ import '@abduljebar/text-editor/dist/index.css';
365
+ import { useForm } from 'react-hook-form';
366
+ import { TextEditor } from "@abduljebar/text-editor";
367
+
368
+ function ArticleForm() {
369
+ const { register, handleSubmit, setValue, watch } = useForm();
370
+
371
+ const handleEditorChange = (content: string, html: string, title?: string) => {
372
+ setValue('content', html);
373
+ setValue('title', title);
374
+ };
375
+
376
+ return (
377
+ <form onSubmit={handleSubmit(data => console.log(data))}>
378
+ <TextEditor
379
+ showSaveTitle={true}
380
+ showButtons={true}
381
+ onChange={handleEditorChange}
382
+ onSave={(content, html) => {
383
+ // Handle form submission
384
+ handleSubmit(data => console.log(data))();
385
+ }}
386
+ />
387
+ </form>
388
+ );
389
+ }
390
+ ```
391
+
392
+ ### Custom Toolbar Implementation
393
+
394
+ ```tsx
395
+ import '@abduljebar/text-editor/dist/index.css';
396
+ import { useTextEditor } from "@abduljebar/text-editor";
397
+
398
+ function CustomToolbarEditor() {
399
+ const { executeCommand, editorRef, insertImage } = useTextEditor({
400
+ initialContent: "Start typing...",
401
+ });
402
+
403
+ const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
404
+ const file = e.target.files?.[0];
405
+ if (file) {
406
+ insertImage(file);
407
+ }
408
+ };
409
+
410
+ return (
411
+ <div className="editor-container">
412
+ <div className="custom-toolbar">
413
+ <button onClick={() => executeCommand('bold')}>Bold</button>
414
+ <button onClick={() => executeCommand('italic')}>Italic</button>
415
+ <button onClick={() => executeCommand('formatBlock', 'h1')}>H1</button>
416
+ <button onClick={() => executeCommand('formatBlock', 'h2')}>H2</button>
417
+ <input type="file" accept="image/*" onChange={handleFileSelect} />
418
+ </div>
419
+ <div
420
+ ref={editorRef}
421
+ contentEditable
422
+ className="editor-content"
423
+ />
424
+ </div>
425
+ );
426
+ }
427
+ ```
428
+
429
+ ### Programmatic Control
430
+
431
+ ```tsx
432
+ import { useRef, useEffect } from 'react';
433
+ import { TextEditor, TextEditorRef } from "@abduljebar/text-editor";
434
+
435
+ function ProgrammaticEditor() {
436
+ const editorRef = useRef<TextEditorRef>(null);
437
+
438
+ useEffect(() => {
439
+ // Example: Auto-insert content after 2 seconds
440
+ const timer = setTimeout(() => {
441
+ if (editorRef.current) {
442
+ editorRef.current.insertText("Hello, world!");
443
+ editorRef.current.focus();
444
+ }
445
+ }, 2000);
446
+
447
+ return () => clearTimeout(timer);
448
+ }, []);
449
+
450
+ const handleCommand = (command: string) => {
451
+ if (editorRef.current) {
452
+ editorRef.current.executeCommand(command);
453
+ }
454
+ };
455
+
456
+ return (
457
+ <div>
458
+ <TextEditor ref={editorRef} />
459
+ <div className="mt-4">
460
+ <button onClick={() => handleCommand('bold')}>Make Selection Bold</button>
461
+ <button onClick={() => editorRef.current?.clear()}>Clear Editor</button>
462
+ </div>
463
+ </div>
464
+ );
465
+ }
466
+ ```
467
+
468
+ ## 📋 Browser Support
469
+
470
+ - Chrome 60+
471
+ - Firefox 55+
472
+ - Safari 12+
473
+ - Edge 79+
474
+ - Opera 47+
475
+
476
+ ## 🔒 Accessibility
477
+
478
+ - Keyboard navigation support
479
+ - ARIA labels for toolbar buttons
480
+ - Focus management
481
+ - Screen reader compatible
482
+ - Proper semantic HTML structure
483
+
484
+ ## 🐛 Troubleshooting
485
+
486
+ ### Common Issues
487
+
488
+ 1. **Toolbar buttons not working**: Ensure the editor is focused and content is selected
489
+ 2. **Images not uploading**: Check CORS settings and upload endpoint configuration
490
+ 3. **Styles not appearing**: Import the CSS file: `import '@abduljebar/text-editor/dist/index.css';`
491
+ 4. **Content not saving**: Check `onSave` callback and validation messages
492
+ 5. **Formatting lost on paste**: Use the built-in `handlePaste` function
493
+
494
+ ### Performance Tips
495
+
496
+ - Use appropriate `debounceDelay` for `onChange` to prevent excessive updates
497
+ - Implement proper image compression before upload
498
+ - Consider using `React.memo` if embedding in frequently re-rendering components
499
+ - Use the ref API for programmatic control instead of frequent state updates
500
+
501
+ ## 📄 Supported Commands
502
+
503
+ The editor supports standard `document.execCommand` APIs:
504
+
505
+ - **Formatting**: `bold`, `italic`, `underline`, `strikeThrough`
506
+ - **Headings**: `formatBlock` (with `h1`, `h2`, `h3`, `p` values)
507
+ - **Lists**: `insertUnorderedList`, `insertOrderedList`
508
+ - **Alignment**: `justifyLeft`, `justifyCenter`, `justifyRight`
509
+ - **Indentation**: `indent`, `outdent`
510
+ - **Links**: `createLink` (with URL value)
511
+ - **History**: `undo`, `redo`
512
+ - **Special**: `superscript`, `subscript`, `formatBlock` (with `blockquote`, `pre` values)
513
+
514
+ ## 🤝 Contributing
515
+
516
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
517
+
518
+ 1. Fork the repository
519
+ 2. Create a feature branch
520
+ 3. Make your changes
521
+ 4. Add tests if applicable
522
+ 5. Submit a pull request
523
+
524
+ ## 📄 License
525
+
526
+ MIT License - see the [LICENSE](LICENSE) file for details.
527
+
528
+ ## 🆘 Support
529
+
530
+ If you encounter any issues or have questions:
531
+
532
+ 1. Check the documentation above
533
+ 2. Search existing GitHub issues
534
+ 3. Create a new issue with:
535
+ - A clear description of the problem
536
+ - Steps to reproduce
537
+ - Expected vs actual behavior
538
+ - Code examples if applicable
539
+
540
+ ## 🚀 Changelog
541
+
542
+ ### v1.1.0
543
+ - Added image upload support with drag & drop
544
+ - Improved toolbar with better selection tracking
545
+ - Added ref API for programmatic control
546
+ - Enhanced keyboard shortcuts
547
+ - Better validation and error handling
548
+ - Added pending images tracking
549
+
550
+ ### v1.0.0
551
+ - Initial release with core editing features
552
+ - Basic text formatting and styling
553
+ - HTML export functionality
554
+ - React hook for advanced usage
555
+
556
+ ---
557
+
558
+ Built with ❤️ by [AbdulJebar Sani](https://github.com/abduljebar49)
559
+
560
+ ## 🔗 Links
561
+
562
+ - [GitHub Repository](https://github.com/abduljebar/text-editor)
563
+ - [npm Package](https://www.npmjs.com/package/@abduljebar/text-editor)
564
+ - [Issue Tracker](https://github.com/abduljebar/text-editor/issues)
565
+ - [Documentation](https://github.com/abduljebar/text-editor#readme)