@layers-app/editor 0.0.1
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 +340 -0
- package/dist/DSD.BSMoqlgJ.js +110636 -0
- package/dist/DSD.BTb8iwne.js +155 -0
- package/dist/DSD.Dps-yU0B.js +253 -0
- package/dist/DSD.rW4l7_6K.js +284 -0
- package/dist/DSD.wx0g6wlB.js +52 -0
- package/dist/index.d.ts +131 -0
- package/dist/index.js +9 -0
- package/dist/index.umd.cjs +915 -0
- package/dist/vite.svg +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# Editor
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Editor is a JavaScript text editor for web applications with a focus on reliability, accessibility, and performance. Editor aims to provide an optimal developer experience so that you can easily prototype and implement features with confidence. Combined with a highly extensible architecture, Editor allows developers to create unique text editors that can scale in both size and functionality.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
import { Editor } from '@layers-app/editor';
|
|
12
|
+
|
|
13
|
+
Initialize the text editor.
|
|
14
|
+
|
|
15
|
+
By default, Editor works with an object and can return either an object or HTML.
|
|
16
|
+
|
|
17
|
+
Example with an object:
|
|
18
|
+
|
|
19
|
+
const text = 'Hello world';
|
|
20
|
+
|
|
21
|
+
const json = {
|
|
22
|
+
root: {
|
|
23
|
+
children: [
|
|
24
|
+
{
|
|
25
|
+
children: [
|
|
26
|
+
{
|
|
27
|
+
detail: 0,
|
|
28
|
+
format: 0,
|
|
29
|
+
mode: 'normal',
|
|
30
|
+
style: '',
|
|
31
|
+
text: text,
|
|
32
|
+
type: 'text',
|
|
33
|
+
version: 1
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
direction: 'ltr',
|
|
37
|
+
format: '',
|
|
38
|
+
indent: 0,
|
|
39
|
+
type: 'paragraph',
|
|
40
|
+
version: 1
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
direction: 'ltr',
|
|
44
|
+
format: '',
|
|
45
|
+
indent: 0,
|
|
46
|
+
type: 'root',
|
|
47
|
+
version: 1
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const onChange = (
|
|
52
|
+
data // json
|
|
53
|
+
) => <Editor initialContent={json} onChange={onChange} />;
|
|
54
|
+
|
|
55
|
+
You can also pass an HTML string to the editor.
|
|
56
|
+
|
|
57
|
+
Example with HTML:
|
|
58
|
+
|
|
59
|
+
const html = `
|
|
60
|
+
<h2 dir="ltr" style="text-align: left;">
|
|
61
|
+
<span style="background-color: rgb(248, 231, 28); font-family: "Trebuchet MS"; white-space: pre-wrap;">Hello</span>
|
|
62
|
+
</h2>
|
|
63
|
+
<h2 dir="ltr">
|
|
64
|
+
<br>
|
|
65
|
+
</h2>
|
|
66
|
+
<p dir="ltr">
|
|
67
|
+
<br>
|
|
68
|
+
</p>
|
|
69
|
+
<p dir="ltr">
|
|
70
|
+
<span style="font-size: 21px; white-space: pre-wrap;">world</span>
|
|
71
|
+
</p>
|
|
72
|
+
`
|
|
73
|
+
|
|
74
|
+
const onChange = (data) => // json
|
|
75
|
+
|
|
76
|
+
<Editor initialContent={html} onChange={onChange} />
|
|
77
|
+
|
|
78
|
+
The outputFormat property controls how the onChange function outputs data. outputFormat can be either "html" or "json". An example with outputFormat:
|
|
79
|
+
|
|
80
|
+
const html = `
|
|
81
|
+
<h2 dir="ltr" style="text-align: left;">
|
|
82
|
+
<span style="background-color: rgb(248, 231, 28); font-family: "Trebuchet MS"; white-space: pre-wrap;">Hello</span>
|
|
83
|
+
</h2>
|
|
84
|
+
<h2 dir="ltr">
|
|
85
|
+
<br>
|
|
86
|
+
</h2>
|
|
87
|
+
<p dir="ltr">
|
|
88
|
+
<br>
|
|
89
|
+
</p>
|
|
90
|
+
<p dir="ltr">
|
|
91
|
+
<span style="font-size: 21px; white-space: pre-wrap;">world</span>
|
|
92
|
+
</p>
|
|
93
|
+
`
|
|
94
|
+
|
|
95
|
+
const onChange = (data) => // html
|
|
96
|
+
|
|
97
|
+
<Editor initialContent={html} outputFormat="html" onChange={onChange} />
|
|
98
|
+
|
|
99
|
+
DocSpaceStylesProvider
|
|
100
|
+
|
|
101
|
+
Use DocSpaceStylesProvider to add styling to your HTML content:
|
|
102
|
+
|
|
103
|
+
<DocSpaceStylesProvider>
|
|
104
|
+
<div
|
|
105
|
+
dangerouslySetInnerHTML={{ __html: '<p>Your html here</p>' }}
|
|
106
|
+
/>
|
|
107
|
+
</DocSpaceStylesProvider>
|
|
108
|
+
|
|
109
|
+
Image Upload
|
|
110
|
+
|
|
111
|
+
To work with image uploads, use the fetchUploadImage function, which takes three parameters: file, success, and error. After your images have been successfully uploaded to your service, you need to call the success function and pass two required arguments: the image URL and ID.
|
|
112
|
+
|
|
113
|
+
const fetchUploadImage = async (
|
|
114
|
+
file: File,
|
|
115
|
+
success: (url: string, id: string) => void,
|
|
116
|
+
error?: (error?: Error) => void
|
|
117
|
+
) => {
|
|
118
|
+
const formData = new FormData();
|
|
119
|
+
formData.append('File', file);
|
|
120
|
+
formData.append('FileAccessModifier', '0');
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const response = await fetch('/api/v1/Files/Upload', {
|
|
124
|
+
method: 'POST',
|
|
125
|
+
body: formData,
|
|
126
|
+
credentials: 'include'
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
throw new Error('File upload failed');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const data = await response.json();
|
|
134
|
+
const { Id, Url } = data;
|
|
135
|
+
|
|
136
|
+
success(Url, Id);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
if (error) {
|
|
139
|
+
if (err instanceof Error) {
|
|
140
|
+
error(err);
|
|
141
|
+
} else {
|
|
142
|
+
error(new Error('An unknown error occurred'));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
<Editor
|
|
149
|
+
{...props}
|
|
150
|
+
fetchUploadImage={fetchUploadImage}
|
|
151
|
+
/>
|
|
152
|
+
|
|
153
|
+
Image Deletion
|
|
154
|
+
|
|
155
|
+
For greater control over image deletion, pass an optional fetchDeleteImage function to the editor. It takes three parameters: id, success, and error. After the image is successfully removed from your service, call the success function.
|
|
156
|
+
|
|
157
|
+
const fetchDeleteImage = async (
|
|
158
|
+
id: string,
|
|
159
|
+
success: () => void,
|
|
160
|
+
error?: (error?: Error) => void
|
|
161
|
+
) => {
|
|
162
|
+
const body = { Ids: [id] };
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
const response = await fetch('/api/v1/Documents/Delete', {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: {
|
|
168
|
+
'Content-Type': 'application/json'
|
|
169
|
+
},
|
|
170
|
+
body: JSON.stringify(body),
|
|
171
|
+
credentials: 'include'
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
await response.json();
|
|
175
|
+
success();
|
|
176
|
+
} catch (err) {
|
|
177
|
+
if (error) {
|
|
178
|
+
if (err instanceof Error) {
|
|
179
|
+
error(err);
|
|
180
|
+
} else {
|
|
181
|
+
error(new Error('An unknown error occurred'));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
<Editor
|
|
188
|
+
{...props}
|
|
189
|
+
fetchUploadImage={fetchUploadImage}
|
|
190
|
+
fetchDeleteImage={fetchDeleteImage}
|
|
191
|
+
/>
|
|
192
|
+
|
|
193
|
+
Additional Options for Image Upload
|
|
194
|
+
|
|
195
|
+
import { Editor, Dropzone } from "@layers-app/editor";
|
|
196
|
+
|
|
197
|
+
const Content = () => (
|
|
198
|
+
<Group justify="center" gap="xl" mih={220} style={{ pointerEvents: 'none' }}>
|
|
199
|
+
{/*
|
|
200
|
+
Dropzone.Accept, Dropzone.Reject, and Dropzone.Idle components are only visible
|
|
201
|
+
when the user performs a specific action:
|
|
202
|
+
|
|
203
|
+
Dropzone.Accept is displayed only when a file that can be accepted is dragged over the dropzone.
|
|
204
|
+
Dropzone.Reject is displayed only when a file that cannot be accepted is dragged over the dropzone.
|
|
205
|
+
Dropzone.Idle is visible when the user is not dragging anything over the dropzone.
|
|
206
|
+
*/}
|
|
207
|
+
<Dropzone.Accept>
|
|
208
|
+
<IconUpload
|
|
209
|
+
style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)' }}
|
|
210
|
+
stroke={1.5}
|
|
211
|
+
/>
|
|
212
|
+
</Dropzone.Accept>
|
|
213
|
+
<Dropzone.Reject>
|
|
214
|
+
<IconX
|
|
215
|
+
style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-red-6)' }}
|
|
216
|
+
stroke={1.5}
|
|
217
|
+
/>
|
|
218
|
+
</Dropzone.Reject>
|
|
219
|
+
<Dropzone.Idle>
|
|
220
|
+
<IconPhoto
|
|
221
|
+
style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-dimmed)' }}
|
|
222
|
+
stroke={1.5}
|
|
223
|
+
/>
|
|
224
|
+
</Dropzone.Idle>
|
|
225
|
+
|
|
226
|
+
<div>
|
|
227
|
+
<Text size="xl" inline>
|
|
228
|
+
Drag images here or click to select files
|
|
229
|
+
</Text>
|
|
230
|
+
<Text size="sm" c="dimmed" inline mt={7}>
|
|
231
|
+
Attach as many files as you like. Each file must not exceed {' '}
|
|
232
|
+
{maxImageSize} MB.
|
|
233
|
+
</Text>
|
|
234
|
+
</div>
|
|
235
|
+
</Group>
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
<Editor
|
|
239
|
+
{...props}
|
|
240
|
+
fetchUploadImage={fetchUploadImage}
|
|
241
|
+
contentModalUploadImage={Content}
|
|
242
|
+
maxImageSize={5}
|
|
243
|
+
maxImageSizeError={() => {}}
|
|
244
|
+
/>
|
|
245
|
+
|
|
246
|
+
Collaboration
|
|
247
|
+
|
|
248
|
+
<Editor
|
|
249
|
+
{...props}
|
|
250
|
+
ws={{
|
|
251
|
+
url: 'https://wss.dudoc.io/', // Websocket URL
|
|
252
|
+
id: '322323', // Unique document ID
|
|
253
|
+
user: userProfile, // Current user
|
|
254
|
+
getActiveUsers: (users) => {
|
|
255
|
+
// Returns the users actively editing the document
|
|
256
|
+
setActiveUsers(users);
|
|
257
|
+
}
|
|
258
|
+
}}
|
|
259
|
+
/>
|
|
260
|
+
|
|
261
|
+
Reset Editor Content
|
|
262
|
+
|
|
263
|
+
import { CLEAR_EDITOR_COMMAND } from './EditorLexical';
|
|
264
|
+
|
|
265
|
+
<>
|
|
266
|
+
<button
|
|
267
|
+
onClick={() => {
|
|
268
|
+
if (editorRef.current) {
|
|
269
|
+
editorRef.current.update(() => {
|
|
270
|
+
editorRef.current?.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}}
|
|
274
|
+
>
|
|
275
|
+
Reset
|
|
276
|
+
</button>
|
|
277
|
+
<Editor
|
|
278
|
+
{...props}
|
|
279
|
+
editorRef={editorRef}
|
|
280
|
+
/>
|
|
281
|
+
</>
|
|
282
|
+
|
|
283
|
+
Properties
|
|
284
|
+
|
|
285
|
+
onChange: (value: string | object) => void
|
|
286
|
+
// Fires whenever the editor changes, returning an HTML string or an object, depending on outputFormat.
|
|
287
|
+
|
|
288
|
+
debounce?: number
|
|
289
|
+
// Controls how often the onChange function is called, in milliseconds.
|
|
290
|
+
|
|
291
|
+
onBlur: (value: string | object) => void
|
|
292
|
+
// Fires when the editor loses focus, returning an HTML string or an object, depending on outputFormat.
|
|
293
|
+
|
|
294
|
+
outputFormat?: 'html' | 'json'
|
|
295
|
+
// Determines if onChange returns HTML or JSON. Default is JSON.
|
|
296
|
+
|
|
297
|
+
initialContent: string | object
|
|
298
|
+
// The initial data for the editor.
|
|
299
|
+
|
|
300
|
+
maxHeight?: number
|
|
301
|
+
// Sets the height of the editor. Default is 100%.
|
|
302
|
+
|
|
303
|
+
mode?: 'simple' | 'default' | 'full' | 'editor'
|
|
304
|
+
// The editor mode, which can restrict or add functionality. Default is 'default'.
|
|
305
|
+
|
|
306
|
+
fetchUploadImage?: (
|
|
307
|
+
file: File,
|
|
308
|
+
success: (url: string, id: string),
|
|
309
|
+
error?: (error?: Error) => void
|
|
310
|
+
) => void
|
|
311
|
+
// Function to upload images to your service.
|
|
312
|
+
|
|
313
|
+
fetchDeleteImage?: (
|
|
314
|
+
id: string,
|
|
315
|
+
success: () => void,
|
|
316
|
+
error?: (error?: Error) => void
|
|
317
|
+
) => void
|
|
318
|
+
// Helper function to delete images.
|
|
319
|
+
|
|
320
|
+
maxImageSize?: number
|
|
321
|
+
// Maximum image size in MB.
|
|
322
|
+
|
|
323
|
+
contentModalUploadImage?: React.FunctionComponent
|
|
324
|
+
// React component to replace the DropZone content.
|
|
325
|
+
|
|
326
|
+
maxImageSizeError?: () => void
|
|
327
|
+
// Function called when the image exceeds maxImageSize.
|
|
328
|
+
|
|
329
|
+
disable?: boolean
|
|
330
|
+
// Toggles read-only mode.
|
|
331
|
+
|
|
332
|
+
ws?: {
|
|
333
|
+
url: string, // Websocket URL
|
|
334
|
+
id: string, // Unique document ID
|
|
335
|
+
user: { color: string; name: string }, // Current user
|
|
336
|
+
getActiveUsers: (users) => void // Returns the users actively editing the document
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
editorRef?: { current: EditorType | null }
|
|
340
|
+
// Reference to the editor.
|