@malaya_jeeva/rich-text-editor 1.0.5 → 1.0.7

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,6 +1,6 @@
1
1
  # 📝 @malaya_jeeva/rich-text-editor
2
2
 
3
- A lightweight, customizable **Rich Text Editor (WYSIWYG)** built with React. Supports formatting, lists, alignment, links, code view, and more.
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,269 @@ 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 { RichTextEditor } from '@malaya_jeeva/rich-text-editor'
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
- <div>
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 of the editor |
43
- | `onChange` | `(value: string) => void` | Callback when content changes |
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
+ | `toolbar` | `ToolbarItem[]` | No | Controls which toolbar buttons are shown. If omitted, all buttons are shown |
53
+
54
+ ### Type export
55
+
56
+ ```ts
57
+ import type { RichTextEditorProps, ToolbarItem } from '@malaya_jeeva/rich-text-editor'
58
+ ```
59
+
60
+ ---
61
+
62
+ ## 🛠️ Toolbar Customization
63
+
64
+ Pass a `toolbar` array to control exactly which buttons appear. If the prop is omitted, **all buttons are shown** — fully backward compatible.
65
+
66
+ ### All available `ToolbarItem` keys
67
+
68
+ | Key | Button | Description |
69
+ | --- | ------ | ----------- |
70
+ | `bold` | **B** | Bold text |
71
+ | `italic` | *I* | Italic text |
72
+ | `underline` | <u>U</u> | Underline text |
73
+ | `color` | A&#818; | Text color picker (palette + HSV wheel + remove) |
74
+ | `blockFormat` | Paragraph ▾ | Block format dropdown (Paragraph, H1, H2, H3) |
75
+ | `alignLeft` | ≡ | Align text left |
76
+ | `alignCenter` | ≡ | Align text center |
77
+ | `alignRight` | ≡ | Align text right |
78
+ | `alignJustify` | ≡ | Justify text |
79
+ | `bulletList` | • | Unordered / bullet list |
80
+ | `numberedList` | 1. | Ordered / numbered list |
81
+ | `indent` | → | Increase indent (or go deeper in list) |
82
+ | `outdent` | ← | Decrease indent (or go back up in list) |
83
+ | `link` | 🔗 | Insert / edit hyperlink |
84
+ | `codeBlock` | `</>` | Wrap selection in `<pre><code>` |
85
+ | `image` | 🖼 | Insert image (upload, URL, or drop) |
86
+ | `table` | ⊞ | Insert table (grid picker up to 8×8) |
87
+ | `html` | HTML | Toggle between Visual and HTML source view |
88
+ | `copyHtml` | ⎘ | Copy current HTML to clipboard |
89
+
90
+ > **Note:** Separators between groups are rendered automatically — they appear only when buttons exist on both sides, so you never get a leading, trailing, or double separator regardless of your selection.
44
91
 
45
92
  ---
46
93
 
47
94
  ## ✨ Features
48
95
 
49
- * Bold, Italic, Underline
50
- * 🎨 Text Color Picker
51
- * 🔠 Headings (H1, H2, H3)
52
- * 📌 Bullet & Numbered Lists
53
- * ↔️ Text Alignment (Left, Center, Right, Justify)
54
- * 🔗 Insert Links
55
- * 💻 Code Block Support
56
- * 🔄 Toggle HTML / Visual Mode
57
- * 📋 Copy HTML Content
58
- * ⌨️ Keyboard Shortcuts (Ctrl+B, Ctrl+I, Ctrl+U)
59
- * 📊 Word Count
96
+ ### Text Formatting
97
+ - **Bold**, *Italic*, <u>Underline</u>
98
+ - 🎨 **Text color picker** — palette + custom HSV color wheel + remove color
99
+ - 🔠 **Block formats** Paragraph, Heading 1 / 2 / 3 (dropdown)
100
+ - ↔️ **Text alignment** Left, Center, Right, Justify
101
+
102
+ ### Lists
103
+ - 📌 **Bullet & Numbered lists** with full multilevel nesting
104
+ - Indent/outdent via toolbar or `Tab` / `Shift+Tab`
105
+ - Nesting style: `1. a. → i.` for ordered, `• → ◦ → ▪` for unordered
106
+
107
+ ### Links
108
+ - 🔗 **Insert link** — floating inline bar appears near the selection
109
+ - **Edit link** — click inside any link to see URL with Edit / Unlink buttons
110
+ - **Unlink** — removes `<a>` tag while keeping the text
111
+
112
+ ### Images
113
+ - 🖼️ **Insert via upload** — drag & drop onto the zone or click to browse
114
+ - 🌐 **Insert via URL** — paste any image URL with live preview
115
+ - 📥 **Drop into editor** — drag an image file directly onto the content
116
+ - **Click to edit** — selecting an image opens a full control panel:
117
+ - **Style tab** — Display (Block / Inline), Alignment (Left / Center / Right), Width presets (25% / 50% / 75% / 100% / Original), manual width input, Alt text
118
+ - **Caption tab** — wraps image in `<figure>/<figcaption>`, editable caption text
119
+ - **Link tab** — wrap image in `<a>` with Apply / Remove
120
+ - 🔲 **Drag-to-resize** — 8 handles (corners preserve aspect ratio, edges resize freely)
121
+
122
+ ### Tables
123
+ - 📊 **Insert table** — grid picker up to 8×8, first row auto-set as `<th>`
124
+ - **Floating context toolbar** — appears near the active cell:
125
+ - Add row above / below, Delete row
126
+ - Add column left / right, Delete column
127
+ - Delete entire table
128
+ - **Cell merge** — drag or `Shift+click` to select a range → Merge button
129
+ - **Cell split** — splits merged cells back to individual cells
130
+ - **Tab navigation** — `Tab` / `Shift+Tab` to move between cells
131
+
132
+ ### Code
133
+ - 💻 **Code block** — wraps selection in `<pre><code>`
134
+ - 🔄 **HTML / Visual toggle** — switch between WYSIWYG and raw HTML source
135
+ - ✨ **Auto-prettify** — HTML view auto-indents on switch
136
+ - 📋 **Copy HTML** — copies current HTML to clipboard
137
+
138
+ ### General
139
+ - ⌨️ **Keyboard shortcuts** — Ctrl+B, Ctrl+I, Ctrl+U
140
+ - 📊 **Live word count**
141
+ - 🌙 **Dark mode support** — automatic via `prefers-color-scheme`
142
+ - 🏗️ **Library-safe TSX** — uses `ReactElement` returns, no global JSX namespace
60
143
 
61
144
  ---
62
145
 
63
146
  ## 🧠 Keyboard Shortcuts
64
147
 
65
- | Shortcut | Action |
66
- | ------------- | --------------------- |
67
- | `Ctrl + B` | Bold |
68
- | `Ctrl + I` | Italic |
69
- | `Ctrl + U` | Underline |
70
- | `Tab` | Indent (inside lists) |
71
- | `Shift + Tab` | Outdent |
148
+ | Shortcut | Action |
149
+ | -------- | ------ |
150
+ | `Ctrl + B` | Bold |
151
+ | `Ctrl + I` | Italic |
152
+ | `Ctrl + U` | Underline |
153
+ | `Tab` | Indent list item / move to next table cell |
154
+ | `Shift + Tab` | Outdent list item / move to previous table cell |
155
+ | `Enter` (link bar) | Apply link |
156
+ | `Escape` (link bar) | Dismiss link bar |
72
157
 
73
158
  ---
74
159
 
75
- ## 🎯 Notes
160
+ ## 🖼️ Image Editor — Detail
161
+
162
+ Click any inserted image to open the image control panel.
163
+
164
+ ### Style tab
165
+ | Control | Options |
166
+ | ------- | ------- |
167
+ | Display | Block (full row) · Inline (flows with text) |
168
+ | Alignment | Left · Center · Right |
169
+ | Width | 25% · 50% · 75% · 100% · Original size · Custom (e.g. `300px`) |
170
+ | Alt text | Free text input |
171
+ | Delete | Removes the image from the editor |
172
+
173
+ ### Caption tab
174
+ Wraps the image in `<figure>` + `<figcaption>`. The caption always renders below the image regardless of float alignment.
175
+
176
+ ### Link tab
177
+ Wraps the image in an `<a>` tag. Existing link can be edited or removed.
76
178
 
77
- * This is a **controlled component** → always pass `value` and `onChange`
78
- * Works with **React 18+ and 19+**
79
- * Compatible with **Next.js** (use `'use client'`)
179
+ ### Drag resize
180
+ Drag any of the 8 blue handles around the selected image:
181
+ - **Corner handles** resize while preserving aspect ratio
182
+ - **Edge handles** — resize width or height freely
80
183
 
81
184
  ---
82
185
 
83
- ## 🔄 Development Workflow
186
+ ## 📊 Table Guide
84
187
 
85
- ### Local Development
188
+ ### Inserting
189
+ 1. Click the table grid icon in the toolbar
190
+ 2. Hover to select rows × columns (up to 8×8)
191
+ 3. Click to insert — first row is automatically `<th>`
86
192
 
87
- ```bash
88
- npm link
193
+ ### Cell merge
194
+ - **Drag** across cells, or **Shift+click** a second cell to select a rectangle
195
+ - Selected cells highlight in blue → click **Merge** in the floating toolbar
196
+
197
+ ### Cell split
198
+ Click inside a merged cell → **Split** button appears in the floating toolbar.
199
+
200
+ ---
201
+
202
+ ## 🎨 Color Picker
203
+
204
+ - **Palette** — 34 preset colors in a compact grid
205
+ - **Black** — one-click reset to automatic color
206
+ - **Remove** — strips color from the selection
207
+ - **Custom** — opens a full HSV color wheel with:
208
+ - Saturation/brightness canvas (drag to pick exact shade)
209
+ - Hue slider (full 360° spectrum)
210
+ - Hex input field
211
+ - Live preview swatch
212
+ - Apply button
213
+
214
+ ---
215
+
216
+ ## 💡 Output Format
217
+
218
+ `onChange` returns standard HTML. Example:
219
+
220
+ ```html
221
+ <h2>Getting started</h2>
222
+ <p>This is a <strong>rich text</strong> editor.</p>
223
+ <ul>
224
+ <li>Item one</li>
225
+ <li>Item two
226
+ <ul><li>Nested item</li></ul>
227
+ </li>
228
+ </ul>
229
+ <figure style="margin:0.8em 0;display:block;overflow:hidden;">
230
+ <img src="..." alt="diagram" style="max-width:100%;width:50%;" />
231
+ <figcaption style="text-align:center;clear:both;">Figure 1</figcaption>
232
+ </figure>
233
+ <table>
234
+ <tr><th>Name</th><th>Role</th></tr>
235
+ <tr><td>Alice</td><td>Engineer</td></tr>
236
+ </table>
89
237
  ```
90
238
 
91
- In your app:
239
+ ### ⚠️ Sanitization
240
+
241
+ The editor does **not** sanitize output. Before persisting to a database or rendering via `dangerouslySetInnerHTML`, run through a sanitizer:
92
242
 
93
243
  ```bash
94
- npm link @malaya_jeeva/rich-text-editor
244
+ npm install dompurify
245
+ npm install -D @types/dompurify
246
+ ```
247
+
248
+ ```ts
249
+ import DOMPurify from 'dompurify'
250
+
251
+ const clean = DOMPurify.sanitize(html)
95
252
  ```
96
253
 
97
254
  ---
98
255
 
99
- ## 📌 Future Improvements
256
+ ## 🌐 Browser Support
257
+
258
+ | Browser | Support |
259
+ | ------- | ------- |
260
+ | Chrome 90+ | ✅ |
261
+ | Firefox 90+ | ✅ |
262
+ | Safari 15+ | ✅ |
263
+ | Edge 90+ | ✅ |
264
+
265
+ ---
100
266
 
101
- * Toolbar customization
102
- * Plugin system
103
- * Image upload support
104
- * Markdown support
105
- * Theme customization
267
+ ## 🎯 Notes
268
+
269
+ - **Controlled component** → always pass `value` and `onChange` together (or omit both)
270
+ - Works with **React 18+ and 19+**
271
+ - Compatible with **Next.js** (use `'use client'`)
272
+ - Written in **TypeScript** — all props and internal types are exported
273
+
274
+ ---
275
+
276
+ ## 🔄 Local Development
277
+
278
+ ```bash
279
+ # In the library folder
280
+ npm run build
281
+ npm link
282
+
283
+ # In your app
284
+ npm link @malaya_jeeva/rich-text-editor
285
+ ```
106
286
 
107
287
  ---
108
288
 
@@ -114,4 +294,4 @@ npm link @malaya_jeeva/rich-text-editor
114
294
 
115
295
  ## 📄 License
116
296
 
117
- ISC
297
+ ISC
package/dist/index.d.mts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { ReactElement } from 'react';
2
2
 
3
+ type ToolbarItem = "bold" | "italic" | "underline" | "color" | "blockFormat" | "alignLeft" | "alignCenter" | "alignRight" | "alignJustify" | "bulletList" | "numberedList" | "indent" | "outdent" | "link" | "codeBlock" | "image" | "table" | "html" | "copyHtml";
3
4
  type RichTextEditorProps = {
4
5
  value?: string;
5
6
  onChange?: (value: string) => void;
7
+ toolbar?: ToolbarItem[];
6
8
  };
7
- declare function RichTextEditor({ value, onChange }: RichTextEditorProps): ReactElement;
8
9
 
9
- export { RichTextEditor, type RichTextEditorProps };
10
+ declare function RichTextEditor({ value, onChange, toolbar }: RichTextEditorProps): ReactElement;
11
+
12
+ export { type RichTextEditorProps, RichTextEditor as default };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import { ReactElement } from 'react';
2
2
 
3
+ type ToolbarItem = "bold" | "italic" | "underline" | "color" | "blockFormat" | "alignLeft" | "alignCenter" | "alignRight" | "alignJustify" | "bulletList" | "numberedList" | "indent" | "outdent" | "link" | "codeBlock" | "image" | "table" | "html" | "copyHtml";
3
4
  type RichTextEditorProps = {
4
5
  value?: string;
5
6
  onChange?: (value: string) => void;
7
+ toolbar?: ToolbarItem[];
6
8
  };
7
- declare function RichTextEditor({ value, onChange }: RichTextEditorProps): ReactElement;
8
9
 
9
- export { RichTextEditor, type RichTextEditorProps };
10
+ declare function RichTextEditor({ value, onChange, toolbar }: RichTextEditorProps): ReactElement;
11
+
12
+ export { type RichTextEditorProps, RichTextEditor as default };