@malaya_jeeva/rich-text-editor 1.0.4 → 1.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 +191 -44
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1315 -490
- package/dist/index.mjs +1301 -472
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 📝 @malaya_jeeva/rich-text-editor
|
|
2
2
|
|
|
3
|
-
A lightweight,
|
|
3
|
+
A lightweight, fully-featured **Rich Text Editor (WYSIWYG)** built from scratch with React + TypeScript. No heavy dependencies — just React.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -20,89 +20,236 @@ npm install @malaya_jeeva/rich-text-editor
|
|
|
20
20
|
'use client' // required for Next.js (App Router)
|
|
21
21
|
|
|
22
22
|
import React, { useState } from 'react'
|
|
23
|
-
import
|
|
23
|
+
import RichTextEditor from '@malaya_jeeva/rich-text-editor'
|
|
24
24
|
|
|
25
25
|
export default function Page() {
|
|
26
26
|
const [value, setValue] = useState('')
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<
|
|
30
|
-
<RichTextEditor value={value} onChange={setValue} />
|
|
31
|
-
</div>
|
|
29
|
+
<RichTextEditor value={value} onChange={setValue} />
|
|
32
30
|
)
|
|
33
31
|
}
|
|
34
32
|
```
|
|
35
33
|
|
|
34
|
+
### Uncontrolled (no props needed)
|
|
35
|
+
|
|
36
|
+
```jsx
|
|
37
|
+
import RichTextEditor from '@malaya_jeeva/rich-text-editor'
|
|
38
|
+
|
|
39
|
+
export default function Page() {
|
|
40
|
+
return <RichTextEditor />
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
36
44
|
---
|
|
37
45
|
|
|
38
46
|
## ⚙️ Props
|
|
39
47
|
|
|
40
|
-
| Prop | Type | Description
|
|
41
|
-
| ---------- | ------------------------- |
|
|
42
|
-
| `value` | `string` | HTML content
|
|
43
|
-
| `onChange` | `(value: string) => void` |
|
|
48
|
+
| Prop | Type | Required | Description |
|
|
49
|
+
| ---------- | ------------------------- | -------- | ---------------------------------------- |
|
|
50
|
+
| `value` | `string` | No | Initial HTML content (read on first mount only) |
|
|
51
|
+
| `onChange` | `(value: string) => void` | No | Fires with full `innerHTML` on every change |
|
|
52
|
+
|
|
53
|
+
### Type export
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import type { RichTextEditorProps } from '@malaya_jeeva/rich-text-editor'
|
|
57
|
+
```
|
|
44
58
|
|
|
45
59
|
---
|
|
46
60
|
|
|
47
61
|
## ✨ Features
|
|
48
62
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
### Text Formatting
|
|
64
|
+
- ✅ **Bold**, *Italic*, <u>Underline</u>
|
|
65
|
+
- 🎨 **Text color picker** — palette + custom HSV color wheel + remove color
|
|
66
|
+
- 🔠 **Block formats** — Paragraph, Heading 1 / 2 / 3 (dropdown)
|
|
67
|
+
- ↔️ **Text alignment** — Left, Center, Right, Justify
|
|
68
|
+
|
|
69
|
+
### Lists
|
|
70
|
+
- 📌 **Bullet & Numbered lists** with full multilevel nesting
|
|
71
|
+
- Indent/outdent via toolbar or `Tab` / `Shift+Tab`
|
|
72
|
+
- Nesting style: `1. → a. → i.` for ordered, `• → ◦ → ▪` for unordered
|
|
73
|
+
|
|
74
|
+
### Links
|
|
75
|
+
- 🔗 **Insert link** — floating inline bar appears near the selection
|
|
76
|
+
- **Edit link** — click inside any link to see URL with Edit / Unlink buttons
|
|
77
|
+
- **Unlink** — removes `<a>` tag while keeping the text
|
|
78
|
+
|
|
79
|
+
### Images
|
|
80
|
+
- 🖼️ **Insert via upload** — drag & drop onto the zone or click to browse
|
|
81
|
+
- 🌐 **Insert via URL** — paste any image URL with live preview
|
|
82
|
+
- 📥 **Drop into editor** — drag an image file directly onto the content
|
|
83
|
+
- **Click to edit** — selecting an image opens a full control panel:
|
|
84
|
+
- **Style tab** — Display (Block / Inline), Alignment (Left / Center / Right), Width presets (25% / 50% / 75% / 100% / Original), manual width input, Alt text
|
|
85
|
+
- **Caption tab** — wraps image in `<figure>/<figcaption>`, editable caption text
|
|
86
|
+
- **Link tab** — wrap image in `<a>` with Apply / Remove
|
|
87
|
+
- 🔲 **Drag-to-resize** — 8 handles (corners preserve aspect ratio, edges resize freely)
|
|
88
|
+
|
|
89
|
+
### Tables
|
|
90
|
+
- 📊 **Insert table** — grid picker up to 8×8, first row auto-set as `<th>`
|
|
91
|
+
- **Floating context toolbar** — appears near the active cell:
|
|
92
|
+
- Add row above / below, Delete row
|
|
93
|
+
- Add column left / right, Delete column
|
|
94
|
+
- Delete entire table
|
|
95
|
+
- **Cell merge** — drag or `Shift+click` to select a range → Merge button
|
|
96
|
+
- **Cell split** — splits merged cells back to individual cells
|
|
97
|
+
- **Tab navigation** — `Tab` / `Shift+Tab` to move between cells
|
|
98
|
+
|
|
99
|
+
### Code
|
|
100
|
+
- 💻 **Code block** — wraps selection in `<pre><code>`
|
|
101
|
+
- 🔄 **HTML / Visual toggle** — switch between WYSIWYG and raw HTML source
|
|
102
|
+
- ✨ **Auto-prettify** — HTML view auto-indents on switch
|
|
103
|
+
- 📋 **Copy HTML** — copies current HTML to clipboard
|
|
104
|
+
|
|
105
|
+
### General
|
|
106
|
+
- ⌨️ **Keyboard shortcuts** — Ctrl+B, Ctrl+I, Ctrl+U
|
|
107
|
+
- 📊 **Live word count**
|
|
108
|
+
- 🌙 **Dark mode support** — automatic via `prefers-color-scheme`
|
|
109
|
+
- 🏗️ **Library-safe TSX** — uses `ReactElement` returns, no global JSX namespace
|
|
60
110
|
|
|
61
111
|
---
|
|
62
112
|
|
|
63
113
|
## 🧠 Keyboard Shortcuts
|
|
64
114
|
|
|
65
|
-
| Shortcut
|
|
66
|
-
|
|
|
67
|
-
| `Ctrl + B`
|
|
68
|
-
| `Ctrl + I`
|
|
69
|
-
| `Ctrl + U`
|
|
70
|
-
| `Tab`
|
|
71
|
-
| `Shift + Tab`
|
|
115
|
+
| Shortcut | Action |
|
|
116
|
+
| --------------- | ---------------------------------- |
|
|
117
|
+
| `Ctrl + B` | Bold |
|
|
118
|
+
| `Ctrl + I` | Italic |
|
|
119
|
+
| `Ctrl + U` | Underline |
|
|
120
|
+
| `Tab` | Indent list item / move to next table cell |
|
|
121
|
+
| `Shift + Tab` | Outdent list item / move to previous table cell |
|
|
122
|
+
| `Enter` (link bar) | Apply link |
|
|
123
|
+
| `Escape` (link bar) | Dismiss link bar |
|
|
72
124
|
|
|
73
125
|
---
|
|
74
126
|
|
|
75
|
-
##
|
|
127
|
+
## 🖼️ Image Editor — Detail
|
|
76
128
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
129
|
+
Click any inserted image to open the image control panel.
|
|
130
|
+
|
|
131
|
+
### Style tab
|
|
132
|
+
| Control | Options |
|
|
133
|
+
| ----------- | ------- |
|
|
134
|
+
| Display | Block (full row) · Inline (flows with text) |
|
|
135
|
+
| Alignment | Left · Center · Right |
|
|
136
|
+
| Width | 25% · 50% · 75% · 100% · Original size · Custom (e.g. `300px`) |
|
|
137
|
+
| Alt text | Free text input |
|
|
138
|
+
| Delete | Removes the image from the editor |
|
|
139
|
+
|
|
140
|
+
### Caption tab
|
|
141
|
+
Wraps the image in `<figure>` + `<figcaption>`. The caption always renders below the image regardless of float alignment.
|
|
142
|
+
|
|
143
|
+
### Link tab
|
|
144
|
+
Wraps the image in an `<a>` tag. Existing link can be edited or removed.
|
|
145
|
+
|
|
146
|
+
### Drag resize
|
|
147
|
+
Drag any of the 8 blue handles around the selected image:
|
|
148
|
+
- **Corner handles** — resize while preserving aspect ratio
|
|
149
|
+
- **Edge handles** — resize width or height freely
|
|
80
150
|
|
|
81
151
|
---
|
|
82
152
|
|
|
83
|
-
##
|
|
153
|
+
## 📊 Table Guide
|
|
84
154
|
|
|
85
|
-
###
|
|
155
|
+
### Inserting
|
|
156
|
+
1. Click the table grid icon in the toolbar
|
|
157
|
+
2. Hover to select rows × columns (up to 8×8)
|
|
158
|
+
3. Click to insert — first row is automatically `<th>`
|
|
86
159
|
|
|
87
|
-
|
|
88
|
-
|
|
160
|
+
### Cell merge
|
|
161
|
+
- **Drag** across cells, or **Shift+click** a second cell to select a rectangle
|
|
162
|
+
- Selected cells highlight in blue → click **Merge** in the floating toolbar
|
|
163
|
+
|
|
164
|
+
### Cell split
|
|
165
|
+
Click inside a merged cell → **Split** button appears in the floating toolbar.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🎨 Color Picker
|
|
170
|
+
|
|
171
|
+
- **Palette** — 34 preset colors in a compact grid
|
|
172
|
+
- **Black** — one-click reset to automatic color
|
|
173
|
+
- **Remove** — strips color from the selection
|
|
174
|
+
- **Custom** — opens a full HSV color wheel with:
|
|
175
|
+
- Saturation/brightness canvas (drag to pick exact shade)
|
|
176
|
+
- Hue slider (full 360° spectrum)
|
|
177
|
+
- Hex input field
|
|
178
|
+
- Live preview swatch
|
|
179
|
+
- Apply button
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 💡 Output Format
|
|
184
|
+
|
|
185
|
+
`onChange` returns standard HTML. Example:
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<h2>Getting started</h2>
|
|
189
|
+
<p>This is a <strong>rich text</strong> editor.</p>
|
|
190
|
+
<ul>
|
|
191
|
+
<li>Item one</li>
|
|
192
|
+
<li>Item two
|
|
193
|
+
<ul><li>Nested item</li></ul>
|
|
194
|
+
</li>
|
|
195
|
+
</ul>
|
|
196
|
+
<figure style="margin:0.8em 0;display:block;overflow:hidden;">
|
|
197
|
+
<img src="..." alt="diagram" style="max-width:100%;width:50%;" />
|
|
198
|
+
<figcaption style="text-align:center;clear:both;">Figure 1</figcaption>
|
|
199
|
+
</figure>
|
|
200
|
+
<table>
|
|
201
|
+
<tr><th>Name</th><th>Role</th></tr>
|
|
202
|
+
<tr><td>Alice</td><td>Engineer</td></tr>
|
|
203
|
+
</table>
|
|
89
204
|
```
|
|
90
205
|
|
|
91
|
-
|
|
206
|
+
### ⚠️ Sanitization
|
|
207
|
+
|
|
208
|
+
The editor does **not** sanitize output. Before persisting to a database or rendering via `dangerouslySetInnerHTML`, run through a sanitizer:
|
|
92
209
|
|
|
93
210
|
```bash
|
|
94
|
-
npm
|
|
211
|
+
npm install dompurify
|
|
212
|
+
npm install -D @types/dompurify
|
|
95
213
|
```
|
|
96
214
|
|
|
215
|
+
```ts
|
|
216
|
+
import DOMPurify from 'dompurify'
|
|
217
|
+
|
|
218
|
+
const clean = DOMPurify.sanitize(html)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 🌐 Browser Support
|
|
224
|
+
|
|
225
|
+
| Browser | Support |
|
|
226
|
+
| ------- | ------- |
|
|
227
|
+
| Chrome 90+ | ✅ |
|
|
228
|
+
| Firefox 90+ | ✅ |
|
|
229
|
+
| Safari 15+ | ✅ |
|
|
230
|
+
| Edge 90+ | ✅ |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 🎯 Notes
|
|
235
|
+
|
|
236
|
+
- **Controlled component** → always pass `value` and `onChange` together (or omit both)
|
|
237
|
+
- Works with **React 18+ and 19+**
|
|
238
|
+
- Compatible with **Next.js** (use `'use client'`)
|
|
239
|
+
- Written in **TypeScript** — all props and internal types are exported
|
|
240
|
+
|
|
97
241
|
---
|
|
98
242
|
|
|
99
|
-
##
|
|
243
|
+
## 🔄 Local Development
|
|
100
244
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
245
|
+
```bash
|
|
246
|
+
# In the library folder
|
|
247
|
+
npm run build
|
|
248
|
+
npm link
|
|
249
|
+
|
|
250
|
+
# In your app
|
|
251
|
+
npm link @malaya_jeeva/rich-text-editor
|
|
252
|
+
```
|
|
106
253
|
|
|
107
254
|
---
|
|
108
255
|
|
|
@@ -114,4 +261,4 @@ npm link @malaya_jeeva/rich-text-editor
|
|
|
114
261
|
|
|
115
262
|
## 📄 License
|
|
116
263
|
|
|
117
|
-
ISC
|
|
264
|
+
ISC
|
package/dist/index.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ type RichTextEditorProps = {
|
|
|
4
4
|
value?: string;
|
|
5
5
|
onChange?: (value: string) => void;
|
|
6
6
|
};
|
|
7
|
+
|
|
7
8
|
declare function RichTextEditor({ value, onChange }: RichTextEditorProps): ReactElement;
|
|
8
9
|
|
|
9
|
-
export {
|
|
10
|
+
export { type RichTextEditorProps, RichTextEditor as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type RichTextEditorProps = {
|
|
|
4
4
|
value?: string;
|
|
5
5
|
onChange?: (value: string) => void;
|
|
6
6
|
};
|
|
7
|
+
|
|
7
8
|
declare function RichTextEditor({ value, onChange }: RichTextEditorProps): ReactElement;
|
|
8
9
|
|
|
9
|
-
export {
|
|
10
|
+
export { type RichTextEditorProps, RichTextEditor as default };
|