nextext-editor 0.1.1 β 0.1.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 +246 -304
- package/dist/block/EditorBlock.d.ts +38 -0
- package/dist/components/Editor.d.ts +4 -31
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/components/block/EditorBlock.d.ts +0 -10
- /package/dist/{components/block β block}/index.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,387 +1,329 @@
|
|
|
1
|
-
#
|
|
1
|
+
# NextText Editor
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> A modern, customizable rich text editor for React with shadcn/ui patterns, Tailwind CSS styling, and collaborative editing powered by Loro CRDT.
|
|
4
4
|
|
|
5
|
-
[](https://github.com)
|
|
7
|
-
[](https://github.com)
|
|
5
|
+
[](https://www.npmjs.com/package/nextext-editor)
|
|
8
6
|
|
|
9
|
-
##
|
|
7
|
+
## Preview
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- π Laggy scrolling with 2,000+ paragraphs
|
|
14
|
-
- πΎ Memory bloat (500MB+ for large docs)
|
|
15
|
-
- π± Crashes on mobile devices
|
|
16
|
-
- β οΈ Poor UX for AI writing assistants
|
|
17
|
-
|
|
18
|
-
**HyperText** uses **virtual scrolling** to render only what's visible:
|
|
19
|
-
|
|
20
|
-
```
|
|
21
|
-
TipTap (10K blocks): HyperText (10K blocks):
|
|
22
|
-
ββ Renders: 10,000 nodes ββ Renders: ~40 nodes
|
|
23
|
-
ββ Memory: 580MB ββ Memory: 48MB (12x less!)
|
|
24
|
-
ββ Scroll: 22 FPS (janky) ββ Scroll: 60 FPS (smooth!)
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Perfect For AI Applications
|
|
28
|
-
|
|
29
|
-
### β
AI Writing Assistants
|
|
30
|
-
```typescript
|
|
31
|
-
// Stream ChatGPT responses without lag
|
|
32
|
-
const { content, updateContent } = useLoroEditor()
|
|
33
|
-
|
|
34
|
-
const streamAI = async () => {
|
|
35
|
-
const response = await fetch('/api/ai/generate')
|
|
36
|
-
const stream = response.body.getReader()
|
|
37
|
-
|
|
38
|
-
while (true) {
|
|
39
|
-
const { done, value } = await stream.read()
|
|
40
|
-
if (done) break
|
|
41
|
-
|
|
42
|
-
updateContent(content + decode(value))
|
|
43
|
-
// β
Smooth even when AI generates 10,000+ words
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### β
Document Generation Platforms
|
|
49
|
-
Generate 20-page contracts, proposals, reportsβall at 60 FPS.
|
|
50
|
-
|
|
51
|
-
### β
Real-Time AI Suggestions
|
|
52
|
-
Analyze entire documents and display 100+ AI suggestions without lag.
|
|
53
|
-
|
|
54
|
-
### β
Collaborative AI Editing
|
|
55
|
-
Built-in Loro CRDT for real-time collaboration (zero config).
|
|
9
|
+

|
|
56
10
|
|
|
57
11
|
## Features
|
|
58
12
|
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
- π¨ **
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
### Installation
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
npm install
|
|
74
|
-
```
|
|
13
|
+
- π¨ **Rich Formatting** - Bold, italic, underline, strikethrough, inline code, text color, and highlighting
|
|
14
|
+
- π **Block Types** - Headings (H1-H6), paragraphs, bullet lists, numbered lists, blockquotes, code blocks, horizontal rules
|
|
15
|
+
- πΌοΈ **Media Support** - Image upload with drag-and-drop (max 5MB, auto-styled)
|
|
16
|
+
- π **Tables** - Insert and edit tables with styled cells
|
|
17
|
+
- π **Built-in Collaboration** - Loro CRDT for conflict-free real-time editing
|
|
18
|
+
- π¨ **Customizable Design** - shadcn/ui-inspired design tokens for easy theming
|
|
19
|
+
- π± **Responsive** - Works seamlessly on desktop and mobile
|
|
20
|
+
- β¨οΈ **Keyboard Shortcuts** - Familiar shortcuts (Ctrl/Cmd+B, I, U, Z, Y)
|
|
21
|
+
- π **Live Preview** - View your content in HTML, Text, or JSON format
|
|
22
|
+
- π **Word & Character Count** - Real-time statistics display
|
|
23
|
+
- π― **TypeScript** - Fully typed for better DX
|
|
75
24
|
|
|
76
|
-
|
|
25
|
+
## Installation
|
|
77
26
|
|
|
78
27
|
```bash
|
|
79
|
-
npm
|
|
28
|
+
npm install nextext-editor
|
|
29
|
+
# or
|
|
30
|
+
yarn add nextext-editor
|
|
31
|
+
# or
|
|
32
|
+
pnpm add nextext-editor
|
|
80
33
|
```
|
|
81
34
|
|
|
82
|
-
|
|
35
|
+
## Quick Start
|
|
83
36
|
|
|
84
|
-
###
|
|
37
|
+
### Basic Usage
|
|
85
38
|
|
|
86
|
-
```
|
|
87
|
-
import {
|
|
88
|
-
import
|
|
39
|
+
```tsx
|
|
40
|
+
import { EditorBlock } from 'nextext-editor';
|
|
41
|
+
import 'nextext-editor/styles.css';
|
|
89
42
|
|
|
90
|
-
function
|
|
91
|
-
|
|
43
|
+
function App() {
|
|
44
|
+
return <EditorBlock placeholder="Start writing..." />;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
92
47
|
|
|
93
|
-
|
|
94
|
-
const response = await openai.chat.completions.create({
|
|
95
|
-
messages: [{ role: 'user', content: prompt }],
|
|
96
|
-
stream: true,
|
|
97
|
-
})
|
|
48
|
+
### With Preview Panel
|
|
98
49
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
updateContent(content + aiContent)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
50
|
+
```tsx
|
|
51
|
+
import { EditorBlock } from 'nextext-editor';
|
|
52
|
+
import 'nextext-editor/styles.css';
|
|
105
53
|
|
|
54
|
+
function App() {
|
|
106
55
|
return (
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
</div>
|
|
113
|
-
)
|
|
56
|
+
<EditorBlock
|
|
57
|
+
showPreview
|
|
58
|
+
placeholder="Start writing..."
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
114
61
|
}
|
|
115
62
|
```
|
|
116
63
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
Run the built-in performance lab to see the difference:
|
|
64
|
+
### Controlled Mode with External State
|
|
120
65
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
3. Enable virtualization
|
|
126
|
-
- FPS jumps to 60
|
|
127
|
-
- Memory drops to ~50MB
|
|
128
|
-
4. Use auto-scroll to stress test
|
|
66
|
+
```tsx
|
|
67
|
+
import { useState } from 'react';
|
|
68
|
+
import { EditorBlock } from 'nextext-editor';
|
|
69
|
+
import 'nextext-editor/styles.css';
|
|
129
70
|
|
|
130
|
-
|
|
71
|
+
function App() {
|
|
72
|
+
const [content, setContent] = useState('<p>Initial content</p>');
|
|
131
73
|
|
|
132
|
-
|
|
74
|
+
return (
|
|
75
|
+
<EditorBlock
|
|
76
|
+
externalContent={content}
|
|
77
|
+
onContentChange={setContent}
|
|
78
|
+
showPreview
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
133
83
|
|
|
134
|
-
|
|
135
|
-
|---------|--------|-----------|
|
|
136
|
-
| **Max document size** | ~2,000 ΒΆ | Unlimited |
|
|
137
|
-
| **FPS (10K blocks)** | 22 FPS | 60 FPS |
|
|
138
|
-
| **Memory (10K blocks)** | 580MB | 48MB |
|
|
139
|
-
| **AI streaming** | Laggy | Smooth |
|
|
140
|
-
| **Collaboration setup** | 50+ lines | 3 lines |
|
|
141
|
-
| **Mobile performance** | Poor | Excellent |
|
|
142
|
-
| **Extension ecosystem** | 100+ | Growing |
|
|
84
|
+
### Using Loro CRDT for Collaboration
|
|
143
85
|
|
|
144
|
-
|
|
86
|
+
```tsx
|
|
87
|
+
import { useLoroEditor, EditorBlock } from 'nextext-editor';
|
|
88
|
+
import 'nextext-editor/styles.css';
|
|
145
89
|
|
|
146
|
-
|
|
90
|
+
function CollaborativeEditor() {
|
|
91
|
+
const { content, updateContent, loroDoc } = useLoroEditor();
|
|
147
92
|
|
|
148
|
-
|
|
149
|
-
Stream AI content without performance issues.
|
|
93
|
+
// Share loroDoc with other clients for real-time sync
|
|
150
94
|
|
|
151
|
-
|
|
152
|
-
|
|
95
|
+
return (
|
|
96
|
+
<EditorBlock
|
|
97
|
+
externalContent={content}
|
|
98
|
+
onContentChange={updateContent}
|
|
99
|
+
/>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
```
|
|
153
103
|
|
|
154
|
-
###
|
|
155
|
-
Analyze 10,000 words and show suggestions while maintaining 60 FPS.
|
|
104
|
+
### Using Editor Directly (Headless)
|
|
156
105
|
|
|
157
|
-
|
|
158
|
-
Team + AI editing simultaneously with Loro CRDT handling conflicts automatically.
|
|
106
|
+
If you want to build your own toolbar and UI, use the low-level `Editor` component:
|
|
159
107
|
|
|
160
|
-
|
|
108
|
+
```tsx
|
|
109
|
+
import { useState } from 'react';
|
|
110
|
+
import { Editor } from 'nextext-editor';
|
|
111
|
+
import 'nextext-editor/styles.css';
|
|
161
112
|
|
|
162
|
-
|
|
113
|
+
function CustomEditor() {
|
|
114
|
+
const [content, setContent] = useState('<p>Start typing...</p>');
|
|
163
115
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
β βββ Real-time FPS measurement
|
|
179
|
-
β βββ Memory monitoring
|
|
180
|
-
β βββ Auto-scroll testing
|
|
181
|
-
β
|
|
182
|
-
βββ Loro CRDT (Collaboration)
|
|
183
|
-
βββ Conflict-free merging
|
|
184
|
-
βββ Offline support
|
|
185
|
-
βββ Real-time sync
|
|
116
|
+
return (
|
|
117
|
+
<div>
|
|
118
|
+
<div className="my-custom-toolbar">
|
|
119
|
+
<button onClick={() => document.execCommand('bold')}>Bold</button>
|
|
120
|
+
<button onClick={() => document.execCommand('italic')}>Italic</button>
|
|
121
|
+
</div>
|
|
122
|
+
<Editor
|
|
123
|
+
content={content}
|
|
124
|
+
onContentChange={setContent}
|
|
125
|
+
placeholder="Write something..."
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
186
130
|
```
|
|
187
131
|
|
|
188
132
|
## Tech Stack
|
|
189
133
|
|
|
190
134
|
- **React 18** - UI framework
|
|
191
135
|
- **TypeScript** - Type safety
|
|
192
|
-
- **Loro CRDT** -
|
|
193
|
-
- **TanStack Virtual** - Virtual scrolling
|
|
194
|
-
- **TanStack Query** - Data fetching
|
|
136
|
+
- **Loro CRDT** - Conflict-free collaboration
|
|
195
137
|
- **Tailwind CSS v4** - Styling
|
|
196
|
-
- **Vite 6** - Build tool
|
|
197
138
|
- **Lucide React** - Icons
|
|
139
|
+
- **Vite** - Build tool
|
|
198
140
|
|
|
199
|
-
##
|
|
141
|
+
## API Reference
|
|
200
142
|
|
|
201
|
-
|
|
202
|
-
- [FPS Measurement Explained](./FPS_MEASUREMENT_EXPLAINED.md)
|
|
203
|
-
- [vs TipTap/ProseMirror](./VS_TIPTAP_PROSEMIRROR.md)
|
|
204
|
-
- [Marketing & Positioning](./MARKETING.md)
|
|
143
|
+
### Editor Props (Core ContentEditable Component)
|
|
205
144
|
|
|
206
|
-
|
|
145
|
+
| Prop | Type | Default | Description |
|
|
146
|
+
|------|------|---------|-------------|
|
|
147
|
+
| `content` | `string` | **required** | HTML content to display |
|
|
148
|
+
| `onContentChange` | `(html: string) => void` | **required** | Called when content changes |
|
|
149
|
+
| `placeholder` | `string` | `"Start typing..."` | Placeholder text when empty |
|
|
150
|
+
| `className` | `string` | - | Custom class for the editable area |
|
|
151
|
+
| `tokens` | `EditorTokens` | `editorTokens` | Custom design tokens |
|
|
207
152
|
|
|
208
|
-
|
|
209
|
-
- **Ctrl/Cmd + I**: Italic
|
|
210
|
-
- **Ctrl/Cmd + U**: Underline
|
|
211
|
-
- **Ctrl/Cmd + Z**: Undo
|
|
212
|
-
- **Ctrl/Cmd + Y**: Redo
|
|
153
|
+
### EditorBlock Props (Complete Editor with Toolbar & Preview)
|
|
213
154
|
|
|
214
|
-
|
|
155
|
+
| Prop | Type | Default | Description |
|
|
156
|
+
|------|------|---------|-------------|
|
|
157
|
+
| `initialContent` | `string` | - | Initial HTML content |
|
|
158
|
+
| `showPreview` | `boolean` | `false` | Show live preview panel |
|
|
159
|
+
| `showToolbar` | `boolean` | `true` | Show formatting toolbar |
|
|
160
|
+
| `externalContent` | `string` | - | Controlled content (for controlled mode) |
|
|
161
|
+
| `onContentChange` | `(html: string) => void` | - | Content change callback |
|
|
162
|
+
| `className` | `string` | - | Custom container class |
|
|
163
|
+
| `placeholder` | `string` | `"Start typing..."` | Placeholder text |
|
|
164
|
+
| `tokens` | `EditorTokens` | `editorTokens` | Custom design tokens |
|
|
215
165
|
|
|
216
|
-
|
|
217
|
-
hyper-text/
|
|
218
|
-
βββ packages/
|
|
219
|
-
β βββ editor/ # @hyper-text/editor (NPM package)
|
|
220
|
-
β βββ src/
|
|
221
|
-
β β βββ components/
|
|
222
|
-
β β β βββ Editor.tsx # Main editor (virtualized + standard)
|
|
223
|
-
β β β βββ Toolbar.tsx # Google Docs toolbar
|
|
224
|
-
β β β βββ HeadingSelector.tsx
|
|
225
|
-
β β β βββ ColorPicker.tsx
|
|
226
|
-
β β β βββ Preview.tsx
|
|
227
|
-
β β βββ hooks/
|
|
228
|
-
β β β βββ useLoroEditor.ts # Loro CRDT hook
|
|
229
|
-
β β βββ types/
|
|
230
|
-
β β β βββ editor.ts # TypeScript types
|
|
231
|
-
β β βββ styles/
|
|
232
|
-
β β βββ editor.css # Editor styles
|
|
233
|
-
β βββ package.json
|
|
234
|
-
β βββ vite.config.ts # Library build config
|
|
235
|
-
β
|
|
236
|
-
βββ apps/
|
|
237
|
-
β βββ demo/ # @hyper-text/demo (Demo app)
|
|
238
|
-
β βββ src/
|
|
239
|
-
β β βββ components/
|
|
240
|
-
β β β βββ PerformanceTestEditor.tsx
|
|
241
|
-
β β β βββ Sidebar.tsx
|
|
242
|
-
β β βββ App.tsx
|
|
243
|
-
β βββ package.json
|
|
244
|
-
β
|
|
245
|
-
βββ pnpm-workspace.yaml # PNPM workspaces config
|
|
246
|
-
βββ package.json # Root monorepo scripts
|
|
247
|
-
βββ tsconfig.json # Root TypeScript config
|
|
248
|
-
βββ README.md
|
|
249
|
-
```
|
|
166
|
+
### useLoroEditor Hook
|
|
250
167
|
|
|
251
|
-
|
|
168
|
+
Returns an object with:
|
|
252
169
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
170
|
+
```tsx
|
|
171
|
+
{
|
|
172
|
+
content: string; // Current HTML content
|
|
173
|
+
format: TextFormat; // Current text format state
|
|
174
|
+
updateContent: (html: string) => void; // Update content
|
|
175
|
+
insertText: (text: string, position?: number) => void; // Insert text
|
|
176
|
+
deleteText: (start: number, length: number) => void; // Delete text
|
|
177
|
+
applyFormat: (start: number, end: number, format: TextFormat) => void; // Apply formatting
|
|
178
|
+
getSnapshot: () => Uint8Array; // Export Loro snapshot
|
|
179
|
+
loadSnapshot: (snapshot: Uint8Array) => void; // Import Loro snapshot
|
|
180
|
+
loroDoc: Loro | null; // Raw Loro document instance
|
|
181
|
+
}
|
|
182
|
+
```
|
|
256
183
|
|
|
257
|
-
|
|
184
|
+
### Design Tokens
|
|
258
185
|
|
|
259
|
-
|
|
186
|
+
Customize the editor's appearance by passing custom tokens:
|
|
260
187
|
|
|
261
|
-
|
|
188
|
+
```tsx
|
|
189
|
+
import { EditorBlock, editorTokens } from 'nextext-editor';
|
|
190
|
+
|
|
191
|
+
const customTokens = {
|
|
192
|
+
...editorTokens,
|
|
193
|
+
container: {
|
|
194
|
+
...editorTokens.container,
|
|
195
|
+
base: 'w-full bg-slate-900 rounded-xl border border-slate-700',
|
|
196
|
+
},
|
|
197
|
+
editor: {
|
|
198
|
+
...editorTokens.editor,
|
|
199
|
+
base: 'min-h-[500px] p-8 text-slate-100',
|
|
200
|
+
},
|
|
201
|
+
};
|
|
262
202
|
|
|
263
|
-
|
|
264
|
-
|
|
203
|
+
function App() {
|
|
204
|
+
return <EditorBlock tokens={customTokens} />;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
265
207
|
|
|
266
|
-
|
|
208
|
+
## Toolbar Actions
|
|
209
|
+
|
|
210
|
+
The editor supports these formatting actions:
|
|
211
|
+
|
|
212
|
+
### Text Formatting
|
|
213
|
+
- `bold` - Toggle bold text
|
|
214
|
+
- `italic` - Toggle italic text
|
|
215
|
+
- `underline` - Toggle underline
|
|
216
|
+
- `strikethrough` - Toggle strikethrough
|
|
217
|
+
- `code` - Toggle inline code
|
|
218
|
+
- `textColor` - Change text color
|
|
219
|
+
- `highlight` - Change background color
|
|
220
|
+
- `clearMarks` - Remove all formatting
|
|
221
|
+
|
|
222
|
+
### Block Types
|
|
223
|
+
- `paragraph` - Normal paragraph
|
|
224
|
+
- `h1`, `h2`, `h3`, `h4`, `h5`, `h6` - Headings
|
|
225
|
+
- `bulletList` - Unordered list
|
|
226
|
+
- `numberedList` - Ordered list
|
|
227
|
+
- `codeBlock` - Code block
|
|
228
|
+
- `blockquote` - Blockquote
|
|
229
|
+
- `clearNodes` - Reset to paragraph
|
|
230
|
+
|
|
231
|
+
### Content
|
|
232
|
+
- `image` - Upload image (max 5MB)
|
|
233
|
+
- `table` - Insert 3x3 table
|
|
234
|
+
- `horizontalRule` - Insert horizontal line
|
|
235
|
+
- `hardBreak` - Insert line break
|
|
236
|
+
|
|
237
|
+
### History
|
|
238
|
+
- `undo` - Undo last change
|
|
239
|
+
- `redo` - Redo last change
|
|
267
240
|
|
|
268
|
-
|
|
269
|
-
# Install dependencies
|
|
270
|
-
pnpm install
|
|
241
|
+
## Keyboard Shortcuts
|
|
271
242
|
|
|
272
|
-
|
|
273
|
-
|
|
243
|
+
- **Ctrl/Cmd + B** - Bold
|
|
244
|
+
- **Ctrl/Cmd + I** - Italic
|
|
245
|
+
- **Ctrl/Cmd + U** - Underline
|
|
246
|
+
- **Ctrl/Cmd + Z** - Undo
|
|
247
|
+
- **Ctrl/Cmd + Y** - Redo
|
|
274
248
|
|
|
275
|
-
|
|
276
|
-
pnpm dev
|
|
277
|
-
```
|
|
249
|
+
## Architecture
|
|
278
250
|
|
|
279
|
-
|
|
251
|
+
The editor follows a clean component hierarchy:
|
|
280
252
|
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
253
|
+
```
|
|
254
|
+
Editor (Core - in components/)
|
|
255
|
+
βββ Low-level contentEditable component
|
|
256
|
+
βββ Handles HTML editing, cursor management, keyboard events
|
|
257
|
+
|
|
258
|
+
EditorBlock (Complete Editor - in block/)
|
|
259
|
+
βββ Uses Editor component
|
|
260
|
+
βββ Adds Toolbar
|
|
261
|
+
βββ Adds Preview panel
|
|
262
|
+
βββ Adds word/character count
|
|
263
|
+
βββ Integrates with Loro CRDT via useLoroEditor hook
|
|
287
264
|
```
|
|
288
265
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
266
|
+
**File Structure:**
|
|
267
|
+
```
|
|
268
|
+
src/
|
|
269
|
+
βββ components/
|
|
270
|
+
β βββ Editor.tsx β Core contentEditable (low-level)
|
|
271
|
+
β βββ Toolbar.tsx
|
|
272
|
+
β βββ Preview.tsx
|
|
273
|
+
β βββ ...
|
|
274
|
+
βββ block/
|
|
275
|
+
β βββ EditorBlock.tsx β Complete editor (high-level)
|
|
276
|
+
βββ hooks/
|
|
277
|
+
β βββ useLoroEditor.ts
|
|
278
|
+
βββ index.ts
|
|
295
279
|
```
|
|
296
280
|
|
|
297
|
-
|
|
281
|
+
## Exported Components
|
|
298
282
|
|
|
299
283
|
```tsx
|
|
300
|
-
import {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
284
|
+
import {
|
|
285
|
+
Editor, // Core contentEditable component (low-level)
|
|
286
|
+
EditorBlock, // Complete editor with toolbar & preview (high-level)
|
|
287
|
+
Toolbar, // Formatting toolbar component
|
|
288
|
+
Preview, // Preview panel component
|
|
289
|
+
ColorPicker, // Color picker dropdown
|
|
290
|
+
HeadingSelector, // Heading selector dropdown
|
|
291
|
+
} from 'nextext-editor';
|
|
306
292
|
```
|
|
307
293
|
|
|
308
|
-
|
|
294
|
+
## Exported Utilities
|
|
309
295
|
|
|
310
296
|
```tsx
|
|
311
|
-
import {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
return (
|
|
318
|
-
<Editor
|
|
319
|
-
externalContent={content}
|
|
320
|
-
onContentChange={updateContent}
|
|
321
|
-
enableVirtualization
|
|
322
|
-
/>
|
|
323
|
-
);
|
|
324
|
-
}
|
|
297
|
+
import {
|
|
298
|
+
useLoroEditor, // Loro CRDT hook
|
|
299
|
+
editorTokens, // Default design tokens
|
|
300
|
+
cn, // className utility (clsx + tailwind-merge)
|
|
301
|
+
} from 'nextext-editor';
|
|
325
302
|
```
|
|
326
303
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
| Prop | Type | Default | Description |
|
|
330
|
-
|------|------|---------|-------------|
|
|
331
|
-
| `enableVirtualization` | `boolean` | `false` | Enable virtualized rendering |
|
|
332
|
-
| `showVirtualizationToggle` | `boolean` | `false` | Show virtualization toggle |
|
|
333
|
-
| `showPreview` | `boolean` | `true` | Show HTML/Text/JSON preview |
|
|
334
|
-
| `externalContent` | `string` | - | Controlled content |
|
|
335
|
-
| `onContentChange` | `(html: string) => void` | - | Content change handler |
|
|
304
|
+
## TypeScript Types
|
|
336
305
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
306
|
+
```tsx
|
|
307
|
+
import type {
|
|
308
|
+
TextFormat, // Text formatting state
|
|
309
|
+
EditorState, // Editor state
|
|
310
|
+
ToolbarAction, // Toolbar action types
|
|
311
|
+
PreviewMode, // Preview mode ('html' | 'text' | 'json')
|
|
312
|
+
EditorTokens, // Design tokens type
|
|
313
|
+
EditorBlockProps, // EditorBlock props
|
|
314
|
+
} from 'nextext-editor';
|
|
344
315
|
```
|
|
345
316
|
|
|
346
|
-
**Results with 10,000 blocks:**
|
|
347
|
-
- **HyperText**: 60 FPS, 48 MB memory, 300 DOM nodes
|
|
348
|
-
- **TipTap**: 22 FPS, 580 MB memory, 30,000 DOM nodes
|
|
349
|
-
|
|
350
|
-
**HyperText is 2.7x faster and uses 12x less memory.** [See full comparison β](./TIPTAP_COMPARISON.md)
|
|
351
|
-
|
|
352
|
-
## Roadmap
|
|
353
|
-
|
|
354
|
-
- [x] Image upload/paste (just added!)
|
|
355
|
-
- [x] TipTap performance comparison tool
|
|
356
|
-
- [ ] Table support
|
|
357
|
-
- [ ] Markdown import/export
|
|
358
|
-
- [ ] Real-time collaboration server
|
|
359
|
-
- [ ] Browser extension
|
|
360
|
-
- [ ] Plugins API
|
|
361
|
-
- [ ] More AI integrations (OpenAI, Anthropic, Cohere)
|
|
362
|
-
- [ ] Mobile app (React Native)
|
|
363
|
-
|
|
364
|
-
## Why This Matters
|
|
365
|
-
|
|
366
|
-
**AI is changing how we create content.**
|
|
367
|
-
|
|
368
|
-
- ChatGPT generates 2,000+ words per response
|
|
369
|
-
- Claude can write 4,000+ word articles
|
|
370
|
-
- AI tools generate entire documents in seconds
|
|
371
|
-
|
|
372
|
-
**Traditional editors weren't built for this.**
|
|
373
|
-
|
|
374
|
-
HyperText was. Built for the AI era. Built for performance. Built for scale.
|
|
375
|
-
|
|
376
317
|
## License
|
|
377
318
|
|
|
378
|
-
MIT
|
|
319
|
+
MIT Β© [NaveenChand](https://github.com/NaveenChand755)
|
|
379
320
|
|
|
380
321
|
## Contributing
|
|
381
322
|
|
|
382
|
-
Contributions welcome! Please
|
|
323
|
+
Contributions are welcome! Please check out the [GitHub repository](https://github.com/NaveenChand755/hyper-text).
|
|
383
324
|
|
|
384
|
-
|
|
325
|
+
## Support
|
|
385
326
|
|
|
386
|
-
|
|
387
|
-
|
|
327
|
+
- π [Report Issues](https://github.com/NaveenChand755/hyper-text/issues)
|
|
328
|
+
- π¬ [Discussions](https://github.com/NaveenChand755/hyper-text/discussions)
|
|
329
|
+
- π [Documentation](https://github.com/NaveenChand755/hyper-text#readme)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { editorTokens } from '../lib/tokens';
|
|
3
|
+
export interface EditorBlockProps {
|
|
4
|
+
/**
|
|
5
|
+
* Initial content (HTML string)
|
|
6
|
+
*/
|
|
7
|
+
initialContent?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Show preview panel
|
|
10
|
+
*/
|
|
11
|
+
showPreview?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Show toolbar
|
|
14
|
+
*/
|
|
15
|
+
showToolbar?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* External content control (for controlled component)
|
|
18
|
+
*/
|
|
19
|
+
externalContent?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Content change handler (for controlled component)
|
|
22
|
+
*/
|
|
23
|
+
onContentChange?: (content: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Custom class name for container
|
|
26
|
+
*/
|
|
27
|
+
className?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Placeholder text
|
|
30
|
+
*/
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Custom design tokens
|
|
34
|
+
*/
|
|
35
|
+
tokens?: typeof editorTokens;
|
|
36
|
+
}
|
|
37
|
+
export declare const EditorBlock: React.NamedExoticComponent<EditorBlockProps>;
|
|
38
|
+
export default EditorBlock;
|