@meenainwal/rich-text-editor 1.1.1 โ 1.2.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/ReadME.md +62 -31
- package/dist/EmojiList-B-C3-zN2.js +25 -0
- package/dist/core/Editor.d.ts +54 -3
- package/dist/core/HistoryManager.d.ts +9 -3
- package/dist/core/SelectionManager.d.ts +21 -0
- package/dist/core/plugins/ImageUploader.d.ts +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/inkflow-editor.mjs +1719 -0
- package/dist/rich-text-editor.css +1 -1
- package/dist/ui/Toolbar.d.ts +1 -0
- package/dist/ui/toolbar/FloatingToolbar.d.ts +16 -0
- package/dist/ui/toolbar/InputModal.d.ts +24 -0
- package/package.json +21 -15
- package/dist/EmojiList-CwY20rtO.js +0 -333
- package/dist/EmojiList-qdrW08up.cjs +0 -1
- package/dist/test-editor.cjs +0 -8
- package/dist/test-editor.mjs +0 -1102
package/ReadME.md
CHANGED
|
@@ -5,7 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
A premium, ultra-lightweight, and framework-agnostic **WYSIWYG rich text editor** built entirely with Vanilla TypeScript. Featuring a sophisticated **Slate & Indigo** design system, it provides a flawless writing experience for React, Next.js, and modern web applications.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
### ๐ก What is WYSIWYG?
|
|
9
|
+
**WYSIWYG** stands for **"What You See Is What You Get"**.
|
|
10
|
+
Unlike markdown or code editors, what you see while typing in InkFlowโthe bold text, centered headings, and interactive tablesโis exactly how it will appear when published. It bridges the gap between editing and the final result, making rich-text creation accessible and predictable.
|
|
11
|
+
|
|
12
|
+
## ๐ Recent Performance & Security Breakthrough (v1.1.2)
|
|
13
|
+
We recently completed an aggressive optimization and security hardening pass:
|
|
14
|
+
- **79% Size Reduction:** Packed weight dropped from **132kB to 28kB**.
|
|
15
|
+
- **9.8/10 Security Score:** Internal audit confirmed world-class XSS protection.
|
|
16
|
+
- **Pure ESM Architecture:** Zero legacy CommonJS bloat for modern bundlers.
|
|
17
|
+
|
|
18
|
+
---
|
|
9
19
|
|
|
10
20
|
## ๐ฎ Live React Preview
|
|
11
21
|
Wanna see it in action? Try the **Interactive React Demo** on StackBlitz:
|
|
@@ -14,8 +24,10 @@ Wanna see it in action? Try the **Interactive React Demo** on StackBlitz:
|
|
|
14
24
|
## โจ Premium Features & Why Choose This Editor?
|
|
15
25
|
|
|
16
26
|
### ๐ Key Pros & Capabilities
|
|
17
|
-
- **Microscopic Footprint**: Only **~
|
|
18
|
-
- **
|
|
27
|
+
- **Microscopic Footprint**: Only **~28kB** packed weight. Total initial load is incredibly light.
|
|
28
|
+
- **Secure By Design**: Rated **9.8/10** in security audits with forced XSS sanitization.
|
|
29
|
+
- **Pure ESM Build**: Optimized for modern bundlers (Vite, Webpack 5, etc.) with zero CJS bloat.
|
|
30
|
+
- **Performance Optimized**: Heavy components like the Emoji Picker are **dynamic-imported** only when clicked.
|
|
19
31
|
- **Framework Agnostic**: Native support for **React**, **Next.js**, **Vue**, **Angular**, and **Svelte**.
|
|
20
32
|
- **Auto-Formatting Magic**: Intelligently parses pasted HTML strings into clean, formatted rich text.
|
|
21
33
|
- **Professional UI/UX**: Modern aesthetics curated with a polished Slate & Indigo color palette.
|
|
@@ -23,6 +35,7 @@ Wanna see it in action? Try the **Interactive React Demo** on StackBlitz:
|
|
|
23
35
|
- **Emoji Picker**: Integrated searchable emoji library for expressive content.
|
|
24
36
|
- **Dark Mode**: Sophisticated dark theme for premium developer experiences.
|
|
25
37
|
- **Customizable Toolbar**: Granular control over tool visibility and layout.
|
|
38
|
+
- **Smart Image Management**: Built-in client-side compression (WebP), loading states, custom upload adapters, live resizing, and native captions.
|
|
26
39
|
|
|
27
40
|
---
|
|
28
41
|
|
|
@@ -39,25 +52,31 @@ We are currently building a dedicated official website to provide the best possi
|
|
|
39
52
|
|
|
40
53
|
---
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
## ๐ก Security & XSS Protection
|
|
56
|
+
InkFlow takes security seriously. It features a hard-coded strict whitelist in `DOMPurify` to ensure:
|
|
57
|
+
- **Malicious Scripts:** Automatically stripped from pastes and API inputs.
|
|
58
|
+
- **URI Blocking:** Blocks `javascript:`, `data:`, and `vbscript:` schemes.
|
|
59
|
+
- **Link Hardening:** Every link is forced to have `rel="noopener noreferrer"`.
|
|
60
|
+
- **Normalization:** Every structural cleanup is followed by a final sanitization pass.
|
|
44
61
|
|
|
45
|
-
|
|
46
|
-
| :--- | :--- | :--- |
|
|
47
|
-
| **Core Bundle (JS)** | ~45 kB | **~11 kB** |
|
|
48
|
-
| **Styles (CSS)** | ~9 kB | **~2 kB** |
|
|
49
|
-
| **Total Initial Load** | **~54 kB** | **~13 kB** |
|
|
50
|
-
| Emoji Picker (Lazy-loaded) | +19 kB | +3 kB |
|
|
62
|
+
---
|
|
51
63
|
|
|
52
64
|
> [!TIP]
|
|
53
65
|
> The editor is optimized for performance. Features like the **Emoji Picker** are only loaded when needed, keeping your initial page load lightning fast.
|
|
54
66
|
|
|
55
67
|
### ๐ Cons (Current Limitations)
|
|
56
|
-
- Base64 image storage can increase the raw output string size for very large images (Backend S3 uploading adapter coming soon).
|
|
57
68
|
- Markdown shortcut typing (e.g., typing `#` for H1) is not natively supported yet.
|
|
58
69
|
|
|
59
70
|
---
|
|
60
71
|
|
|
72
|
+
## ๐ Technical Guides
|
|
73
|
+
For deep-dive documentation, check out our local guides:
|
|
74
|
+
- [**Usage Guide**](./USAGE_GUIDE.md): Configuration, API methods, and feature customization.
|
|
75
|
+
- [**Technical Integration Guide**](./INTEGRATION_GUIDE.md): Step-by-step setup and advanced patterns.
|
|
76
|
+
- [**Security Report**](./SECURITY_REPORT.md): Full breakdown of our XSS protection and hardening.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
61
80
|
## ๐ฆ Installation
|
|
62
81
|
|
|
63
82
|
```bash
|
|
@@ -69,11 +88,11 @@ npm install @meenainwal/rich-text-editor
|
|
|
69
88
|
### Basic Usage (Vanilla JS)
|
|
70
89
|
|
|
71
90
|
```javascript
|
|
72
|
-
import {
|
|
91
|
+
import { InkFlowEditor } from '@meenainwal/rich-text-editor';
|
|
73
92
|
import '@meenainwal/rich-text-editor/style'; // Simple style import
|
|
74
93
|
|
|
75
94
|
const container = document.getElementById('editor');
|
|
76
|
-
const editor = new
|
|
95
|
+
const editor = new InkFlowEditor(container, {
|
|
77
96
|
placeholder: 'Type something beautiful...',
|
|
78
97
|
autofocus: true,
|
|
79
98
|
showStatus: true,
|
|
@@ -86,16 +105,16 @@ In React **Strict Mode**, components mount twice in development. Always use the
|
|
|
86
105
|
|
|
87
106
|
```tsx
|
|
88
107
|
import { useEffect, useRef } from 'react';
|
|
89
|
-
import {
|
|
108
|
+
import { InkFlowEditor } from '@meenainwal/rich-text-editor';
|
|
90
109
|
import '@meenainwal/rich-text-editor/style';
|
|
91
110
|
|
|
92
111
|
export default function App() {
|
|
93
112
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
94
|
-
const editorRef = useRef<
|
|
113
|
+
const editorRef = useRef<InkFlowEditor | null>(null);
|
|
95
114
|
|
|
96
115
|
useEffect(() => {
|
|
97
116
|
if (containerRef.current && !editorRef.current) {
|
|
98
|
-
editorRef.current = new
|
|
117
|
+
editorRef.current = new InkFlowEditor(containerRef.current, {
|
|
99
118
|
placeholder: 'Start writing...',
|
|
100
119
|
});
|
|
101
120
|
}
|
|
@@ -118,7 +137,7 @@ For Next.js, ensure the editor is only initialized on the client side using `use
|
|
|
118
137
|
```tsx
|
|
119
138
|
"use client";
|
|
120
139
|
import { useEffect, useRef } from 'react';
|
|
121
|
-
import {
|
|
140
|
+
import { InkFlowEditor } from '@meenainwal/rich-text-editor';
|
|
122
141
|
import '@meenainwal/rich-text-editor/style';
|
|
123
142
|
|
|
124
143
|
export default function MyEditor() {
|
|
@@ -127,7 +146,7 @@ export default function MyEditor() {
|
|
|
127
146
|
useEffect(() => {
|
|
128
147
|
if (!containerRef.current) return;
|
|
129
148
|
|
|
130
|
-
const editor = new
|
|
149
|
+
const editor = new InkFlowEditor(containerRef.current, {
|
|
131
150
|
onSave: (html) => console.log(html)
|
|
132
151
|
});
|
|
133
152
|
|
|
@@ -151,6 +170,9 @@ export default function MyEditor() {
|
|
|
151
170
|
| `toolbarItems` | `string[]` | `all` | Array of tool IDs to display (e.g., `['bold', 'table']`). |
|
|
152
171
|
| `onSave` | `function` | `undefined` | Callback triggered when content is saved. |
|
|
153
172
|
| `autoSaveInterval` | `number` | `1000` | Delay in ms before auto-save triggers after typing. |
|
|
173
|
+
| `imageEndpoints` | `object` | `undefined` | Custom upload endpoint configuration: `{ upload: string }`. |
|
|
174
|
+
| `cloudinaryFallback` | `object` | `undefined` | Cloudinary settings: `{ cloudName: string, uploadPreset: string }`. |
|
|
175
|
+
| `maxImageSizeMB` | `number` | `5` | Maximum image size in MB (enforced pre and post compression). |
|
|
154
176
|
|
|
155
177
|
## ๐ API Methods
|
|
156
178
|
|
|
@@ -160,25 +182,34 @@ export default function MyEditor() {
|
|
|
160
182
|
- `focus()`: Forces focus onto the editor.
|
|
161
183
|
- `setDarkMode(boolean)`: Dynamically toggle dark mode.
|
|
162
184
|
- `insertTable(rows, cols)`: Programmatically insert a table.
|
|
185
|
+
- `insertImage(url, id, isLoading)`: Programmatically insert an image with optional loading state.
|
|
163
186
|
|
|
164
187
|
## ๐ก Troubleshooting: Duplicate Editors?
|
|
165
188
|
If you see multiple toolbars or editors, it's likely because:
|
|
166
189
|
1. **React Strict Mode**: Ensure you call `editor.destroy()` in the `useEffect` cleanup.
|
|
167
190
|
2. **Missing Cleanup**: The editor injects elements into the DOM; if you don't destroy it when the component unmounts, those elements remain.
|
|
168
191
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
### ๐ Bug Fixes
|
|
172
|
-
- **Fixed Missing `destroy()` Export**: Resolved TypeScript error where the `destroy()` method was missing from the generated type declarations.
|
|
173
|
-
- **Image Resizer Cleanup**: Fixed a memory leak where window-level event listeners for image resizing were not being removed on editor destruction.
|
|
174
|
-
- **Double Initializing Failsafe**: Added an internal check to clear the container before initialization, preventing duplicate editors in React Strict Mode.
|
|
175
|
-
- **Lazy-Loaded Emojis**: Moved the Emoji List to a separate chunk (~19kB) that only loads when the picker is opened, reducing the initial bundle size.
|
|
192
|
+
---
|
|
176
193
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
- **
|
|
181
|
-
- **
|
|
194
|
+
## ๐ Patch Notes
|
|
195
|
+
|
|
196
|
+
### v1.2.0 (Premium UI & Image Power-Up)
|
|
197
|
+
- **Lucide Icon Upgrade**: Replaced all 27 toolbar icons with high-quality, professional Lucide-styled SVGs.
|
|
198
|
+
- **Initialization Loader**: Added a sophisticated shimmering glassmorphism loader for a smoother startup experience.
|
|
199
|
+
- **Advanced Image Pipeline**: Added drag-and-drop support with automatic client-side **WebP compression**.
|
|
200
|
+
- **Interactive UX**: Added loading state previews, 4-corner resizing handles, and native `<figcaption>` support.
|
|
201
|
+
- **Glassmorphism Design**: Enhanced modals and loaders with modern backdrop-blur effects.
|
|
202
|
+
|
|
203
|
+
### v1.1.2 (Security & Performance)
|
|
204
|
+
- **Aggressive Size Optimization**: Reduced packed size to **28kB** by moving to ESM-only and pruning datasets.
|
|
205
|
+
- **Hardened Sanitization**: Centralized all HTML processing through a unified security layer (Rating 9.8/10).
|
|
206
|
+
- **Safe UI Rendering**: Eliminated `innerHTML` usage in all UI components for zero-trust text rendering.
|
|
207
|
+
- **CJS Build Deprecation**: Removed CommonJS versions to optimize for modern ESM-based environments.
|
|
208
|
+
|
|
209
|
+
### v1.1.1 (Quick Fixes)
|
|
210
|
+
- Fixed missing `destroy()` export.
|
|
211
|
+
- Resolved memory leaks in image resizer.
|
|
212
|
+
- Prevented duplicate editors in React Strict Mode.
|
|
182
213
|
|
|
183
214
|
---
|
|
184
215
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const e = [
|
|
2
|
+
{ emoji: "๐", name: "grinning", category: "Smileys" },
|
|
3
|
+
{ emoji: "๐", name: "smiley", category: "Smileys" },
|
|
4
|
+
{ emoji: "๐", name: "smile", category: "Smileys" },
|
|
5
|
+
{ emoji: "๐", name: "grin", category: "Smileys" },
|
|
6
|
+
{ emoji: "๐", name: "laughing", category: "Smileys" },
|
|
7
|
+
{ emoji: "๐
", name: "sweat smile", category: "Smileys" },
|
|
8
|
+
{ emoji: "๐", name: "joy", category: "Smileys" },
|
|
9
|
+
{ emoji: "๐", name: "slight smile", category: "Smileys" },
|
|
10
|
+
{ emoji: "๐", name: "wink", category: "Smileys" },
|
|
11
|
+
{ emoji: "๐", name: "blush", category: "Smileys" },
|
|
12
|
+
{ emoji: "๐", name: "heart eyes", category: "Smileys" },
|
|
13
|
+
{ emoji: "๐", name: "kissing heart", category: "Smileys" },
|
|
14
|
+
{ emoji: "๐", name: "thumbs up", category: "Hands" },
|
|
15
|
+
{ emoji: "๐", name: "thumbs down", category: "Hands" },
|
|
16
|
+
{ emoji: "โค๏ธ", name: "heart", category: "Symbols" },
|
|
17
|
+
{ emoji: "โจ", name: "sparkles", category: "Symbols" },
|
|
18
|
+
{ emoji: "๐ฅ", name: "fire", category: "Symbols" },
|
|
19
|
+
{ emoji: "โ
", name: "check", category: "Symbols" },
|
|
20
|
+
{ emoji: "๐", name: "party", category: "Activities" },
|
|
21
|
+
{ emoji: "๐", name: "rocket", category: "Travel" }
|
|
22
|
+
];
|
|
23
|
+
export {
|
|
24
|
+
e as EMOJI_LIST
|
|
25
|
+
};
|
package/dist/core/Editor.d.ts
CHANGED
|
@@ -31,7 +31,18 @@ export interface EditorOptions {
|
|
|
31
31
|
autoSaveInterval?: number;
|
|
32
32
|
autoSave?: boolean;
|
|
33
33
|
showStatus?: boolean;
|
|
34
|
+
showLoader?: boolean;
|
|
34
35
|
toolbarItems?: string[];
|
|
36
|
+
imageEndpoints?: {
|
|
37
|
+
upload: string;
|
|
38
|
+
delete: string;
|
|
39
|
+
};
|
|
40
|
+
cloudinaryFallback?: {
|
|
41
|
+
cloudName: string;
|
|
42
|
+
uploadPreset: string;
|
|
43
|
+
};
|
|
44
|
+
maxImageSizeMB?: number;
|
|
45
|
+
onImageDelete?: (imageId?: string, imageUrl?: string) => void;
|
|
35
46
|
}
|
|
36
47
|
export declare class CoreEditor {
|
|
37
48
|
protected container: HTMLElement;
|
|
@@ -44,7 +55,10 @@ export declare class CoreEditor {
|
|
|
44
55
|
private historyTimeout;
|
|
45
56
|
private pendingStyles;
|
|
46
57
|
private observer;
|
|
58
|
+
private floatingToolbar;
|
|
47
59
|
private eventListeners;
|
|
60
|
+
private loaderElement;
|
|
61
|
+
private isUndoingRedoing;
|
|
48
62
|
constructor(container: HTMLElement, options?: EditorOptions);
|
|
49
63
|
/**
|
|
50
64
|
* Applies custom theme variables to the editor container.
|
|
@@ -66,13 +80,19 @@ export declare class CoreEditor {
|
|
|
66
80
|
*/
|
|
67
81
|
private wrapImage;
|
|
68
82
|
protected setupInputHandlers(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Immediately records a history state if one is pending.
|
|
85
|
+
*/
|
|
86
|
+
private flushHistoryRecord;
|
|
69
87
|
private handleInput;
|
|
70
88
|
private scheduleHistoryRecord;
|
|
71
89
|
private scheduleAutoSave;
|
|
72
90
|
save(): void;
|
|
73
91
|
undo(): void;
|
|
74
92
|
redo(): void;
|
|
75
|
-
|
|
93
|
+
protected triggerChange(): void;
|
|
94
|
+
private createLoader;
|
|
95
|
+
private hideLoader;
|
|
76
96
|
protected createEditableElement(): HTMLElement;
|
|
77
97
|
/**
|
|
78
98
|
* Focuses the editor.
|
|
@@ -82,6 +102,10 @@ export declare class CoreEditor {
|
|
|
82
102
|
* Executes a command on the current selection.
|
|
83
103
|
*/
|
|
84
104
|
execute(command: string, value?: string | null): void;
|
|
105
|
+
/**
|
|
106
|
+
* Special handler for links to open them in a new tab when clicked.
|
|
107
|
+
*/
|
|
108
|
+
private setupLinkClickHandlers;
|
|
85
109
|
/**
|
|
86
110
|
* Inserts a table at the current selection.
|
|
87
111
|
*/
|
|
@@ -108,12 +132,21 @@ export declare class CoreEditor {
|
|
|
108
132
|
* Recursively removes a style property from all elements in a fragment.
|
|
109
133
|
*/
|
|
110
134
|
private clearStyleRecursive;
|
|
135
|
+
/**
|
|
136
|
+
* Applies an inline style to the selection.
|
|
137
|
+
* This is used for properties like font-size (px) and font-family
|
|
138
|
+
* where execCommand is outdated or limited.
|
|
139
|
+
*/
|
|
111
140
|
/**
|
|
112
141
|
* Applies an inline style to the selection.
|
|
113
142
|
* This is used for properties like font-size (px) and font-family
|
|
114
143
|
* where execCommand is outdated or limited.
|
|
115
144
|
*/
|
|
116
145
|
setStyle(property: string, value: string, range?: Range): Range | null;
|
|
146
|
+
/**
|
|
147
|
+
* Applies a style to the block-level containers within the range.
|
|
148
|
+
*/
|
|
149
|
+
private setBlockStyle;
|
|
117
150
|
/**
|
|
118
151
|
* Creates a link at the current selection.
|
|
119
152
|
* Ensures the link opens in a new tab with proper security attributes.
|
|
@@ -122,11 +155,25 @@ export declare class CoreEditor {
|
|
|
122
155
|
/**
|
|
123
156
|
* Inserts an image at the current selection.
|
|
124
157
|
*/
|
|
125
|
-
insertImage(url: string):
|
|
158
|
+
insertImage(url: string, id?: string, isLoading?: boolean): HTMLElement | null;
|
|
126
159
|
/**
|
|
127
|
-
* Returns the clean HTML content of the editor.
|
|
160
|
+
* Returns the clean and optimized HTML content of the editor.
|
|
128
161
|
*/
|
|
129
162
|
getHTML(): string;
|
|
163
|
+
/**
|
|
164
|
+
* Normalizes the editor's content in-place.
|
|
165
|
+
*/
|
|
166
|
+
normalize(): void;
|
|
167
|
+
private normalizationContainer;
|
|
168
|
+
/**
|
|
169
|
+
* Internal helper to strictly sanitize HTML strings.
|
|
170
|
+
*/
|
|
171
|
+
private sanitize;
|
|
172
|
+
/**
|
|
173
|
+
* Optimizes HTML by fixing invalid nesting and removing redundant tags.
|
|
174
|
+
*/
|
|
175
|
+
private normalizeHTML;
|
|
176
|
+
private handlePaste;
|
|
130
177
|
/**
|
|
131
178
|
* Sets the HTML content of the editor.
|
|
132
179
|
*/
|
|
@@ -139,4 +186,8 @@ export declare class CoreEditor {
|
|
|
139
186
|
* Returns the editor options.
|
|
140
187
|
*/
|
|
141
188
|
getOptions(): EditorOptions;
|
|
189
|
+
/**
|
|
190
|
+
* Internal helper to handle multiple files.
|
|
191
|
+
*/
|
|
192
|
+
handleFiles(files: File[]): Promise<void>;
|
|
142
193
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export interface HistoryState {
|
|
2
2
|
html: string;
|
|
3
|
+
selection: {
|
|
4
|
+
startPath: number[];
|
|
5
|
+
startOffset: number;
|
|
6
|
+
endPath: number[];
|
|
7
|
+
endOffset: number;
|
|
8
|
+
} | null;
|
|
3
9
|
}
|
|
4
10
|
export declare class HistoryManager {
|
|
5
11
|
private stack;
|
|
@@ -10,15 +16,15 @@ export declare class HistoryManager {
|
|
|
10
16
|
* Records a new state in the history stack.
|
|
11
17
|
* Clears any "redo" states if we record a new action.
|
|
12
18
|
*/
|
|
13
|
-
record(html: string): void;
|
|
19
|
+
record(html: string, selection: HistoryState['selection'] | null): void;
|
|
14
20
|
/**
|
|
15
21
|
* Returns the previous state if available.
|
|
16
22
|
*/
|
|
17
|
-
undo():
|
|
23
|
+
undo(): HistoryState | null;
|
|
18
24
|
/**
|
|
19
25
|
* Returns the next state if available.
|
|
20
26
|
*/
|
|
21
|
-
redo():
|
|
27
|
+
redo(): HistoryState | null;
|
|
22
28
|
/**
|
|
23
29
|
* Checks if undo is possible.
|
|
24
30
|
*/
|
|
@@ -12,6 +12,27 @@ export declare class SelectionManager {
|
|
|
12
12
|
* Returns the first range of the current selection.
|
|
13
13
|
*/
|
|
14
14
|
getRange(): Range | null;
|
|
15
|
+
/**
|
|
16
|
+
* Serializes the current selection into a path-based format relative to a root element.
|
|
17
|
+
* This allows restoring selection even if the DOM nodes are replaced but the structure is similar.
|
|
18
|
+
*/
|
|
19
|
+
getSelectionPath(root: HTMLElement): {
|
|
20
|
+
startPath: number[];
|
|
21
|
+
startOffset: number;
|
|
22
|
+
endPath: number[];
|
|
23
|
+
endOffset: number;
|
|
24
|
+
} | null;
|
|
25
|
+
/**
|
|
26
|
+
* Restores selection from a path-based serialization.
|
|
27
|
+
*/
|
|
28
|
+
restoreSelectionPath(root: HTMLElement, path: {
|
|
29
|
+
startPath: number[];
|
|
30
|
+
startOffset: number;
|
|
31
|
+
endPath: number[];
|
|
32
|
+
endOffset: number;
|
|
33
|
+
} | null): void;
|
|
34
|
+
private getNodePath;
|
|
35
|
+
private getNodeByPath;
|
|
15
36
|
/**
|
|
16
37
|
* Saves the current selection range.
|
|
17
38
|
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EditorOptions } from '../Editor';
|
|
2
|
+
export interface UploadResult {
|
|
3
|
+
imageUrl: string;
|
|
4
|
+
imageId?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class ImageUploader {
|
|
7
|
+
/**
|
|
8
|
+
* Compresses an image file using HTML5 Canvas.
|
|
9
|
+
*/
|
|
10
|
+
static compressImage(file: File, maxSizeMB: number): Promise<File | Blob>;
|
|
11
|
+
/**
|
|
12
|
+
* Uploads a file based on editor configuration.
|
|
13
|
+
*/
|
|
14
|
+
static uploadFile(file: File | Blob, options: EditorOptions): Promise<UploadResult | null>;
|
|
15
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CoreEditor, EditorOptions } from './core/Editor';
|
|
2
2
|
import { Toolbar } from './ui/Toolbar';
|
|
3
|
-
export declare class
|
|
3
|
+
export declare class InkFlowEditor extends CoreEditor {
|
|
4
4
|
private toolbar;
|
|
5
5
|
constructor(container: HTMLElement, options?: EditorOptions);
|
|
6
6
|
getToolbar(): Toolbar;
|