dn-react-text-editor 0.1.0 → 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 +2 -221
- package/dist/attach_file.d.mts +5 -1
- package/dist/attach_file.d.ts +5 -1
- package/dist/attach_file.js +18 -9
- package/dist/attach_file.mjs +17 -9
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -51
- package/dist/index.mjs +49 -52
- package/dist/text_editor.d.mts +2 -1
- package/dist/text_editor.d.ts +2 -1
- package/dist/text_editor.js +44 -51
- package/dist/text_editor.mjs +48 -52
- package/package.json +53 -53
package/README.md
CHANGED
|
@@ -1,222 +1,3 @@
|
|
|
1
|
-
# React
|
|
1
|
+
# React Text Editor
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
It eliminates repetitive code required to implement state changes and subscriptions for input elements, and provides a simple interface.
|
|
6
|
-
|
|
7
|
-
At the same time, it allows you to use all the attributes originally provided by the input tag as-is, without needing to learn this package.
|
|
8
|
-
|
|
9
|
-
## Get Started
|
|
10
|
-
|
|
11
|
-
This is a simple example of how to use this package.
|
|
12
|
-
|
|
13
|
-
```tsx
|
|
14
|
-
import { useFormStore } from "dn-react-input";
|
|
15
|
-
|
|
16
|
-
export default function App() {
|
|
17
|
-
const store = useFormStore({
|
|
18
|
-
email: "",
|
|
19
|
-
password: "",
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const submit = async () => {
|
|
23
|
-
const { email, password } = store.state;
|
|
24
|
-
|
|
25
|
-
alert(`Email: ${email}\nPassword: ${password}`);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<form
|
|
30
|
-
onSubmit={(e) => {
|
|
31
|
-
e.preventDefault();
|
|
32
|
-
submit();
|
|
33
|
-
}}
|
|
34
|
-
>
|
|
35
|
-
<store.input name="email" type="email" />
|
|
36
|
-
<store.input name="password" type="password" />
|
|
37
|
-
<button type="submit">Submit</button>
|
|
38
|
-
</form>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## How to define state?
|
|
44
|
-
|
|
45
|
-
You can define any state you want as an object when calling `useStore`.
|
|
46
|
-
|
|
47
|
-
```tsx
|
|
48
|
-
function Component() {
|
|
49
|
-
...
|
|
50
|
-
|
|
51
|
-
const store = useStore({
|
|
52
|
-
email: "",
|
|
53
|
-
password: "",
|
|
54
|
-
rememberMe: false,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
...
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
It's a single source of truth for your form state.
|
|
62
|
-
|
|
63
|
-
## How to get input values?
|
|
64
|
-
|
|
65
|
-
You can access the current values of the input elements through the `state` property of the store.
|
|
66
|
-
|
|
67
|
-
```tsx
|
|
68
|
-
function Component() {
|
|
69
|
-
...
|
|
70
|
-
|
|
71
|
-
const submit = () => {
|
|
72
|
-
const { email, password, rememberMe } = store.state;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
...
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## How to add input elements?
|
|
80
|
-
|
|
81
|
-
You can add input elements using the `Input` component provided by the store. There are 'Select' and 'Textarea' components as well.
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
import { Input } from "dn-react-input";
|
|
85
|
-
|
|
86
|
-
function Component() {
|
|
87
|
-
...
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<form>
|
|
91
|
-
<Input store={store} name="email" type="email" />
|
|
92
|
-
<Input store={store} name="password" type="password" />
|
|
93
|
-
<Input store={store} name="rememberMe" type="checkbox" />
|
|
94
|
-
</form>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
If you want to avoid passing the store to each input component, use `useStoreInput`. This hook provides input components that are already connected to the store.
|
|
100
|
-
|
|
101
|
-
```tsx
|
|
102
|
-
import { useStoreInput } from "dn-react-input";
|
|
103
|
-
|
|
104
|
-
function Component() {
|
|
105
|
-
...
|
|
106
|
-
const Input = useStoreInput(store);
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<form>
|
|
110
|
-
<Input.input name="email" type="email" />
|
|
111
|
-
<Input.input name="password" type="password" />
|
|
112
|
-
<Input.input name="rememberMe" type="checkbox" />
|
|
113
|
-
</form>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
`useFormStore` is a facade that combines `useStore` and `useStoreInput` for convenience.
|
|
119
|
-
|
|
120
|
-
```tsx
|
|
121
|
-
import { useFormStore } from "dn-react-input";
|
|
122
|
-
|
|
123
|
-
function Component() {
|
|
124
|
-
...
|
|
125
|
-
const store = useFormStore({
|
|
126
|
-
email: "",
|
|
127
|
-
password: "",
|
|
128
|
-
rememberMe: false,
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<form>
|
|
133
|
-
<store.input name="email" type="email" />
|
|
134
|
-
<store.input name="password" type="password" />
|
|
135
|
-
<store.input name="rememberMe" type="checkbox" />
|
|
136
|
-
</form>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## How to render components on state changes?
|
|
142
|
-
|
|
143
|
-
If you want to render a component only when specific parts of the state change, use the `useSelector` hook.
|
|
144
|
-
|
|
145
|
-
```tsx
|
|
146
|
-
import { useSelector } from "dn-react-input";
|
|
147
|
-
|
|
148
|
-
function Component() {
|
|
149
|
-
...
|
|
150
|
-
const email = useSelector(store, (state) => state.email);
|
|
151
|
-
|
|
152
|
-
return <div>Your email is: {email}</div>;
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
If you want to render components in an inline manner, use the `createRender` function. By using this, you can avoid creating separate components for each part of the state you want to track.
|
|
157
|
-
|
|
158
|
-
```tsx
|
|
159
|
-
import { createRender } from "dn-react-input";
|
|
160
|
-
|
|
161
|
-
function Component() {
|
|
162
|
-
...
|
|
163
|
-
return (
|
|
164
|
-
<div>
|
|
165
|
-
{createRender(store, (state) => <p>{state.email}</p>)}
|
|
166
|
-
{createRender(store, (state) => <p>{state.password}</p>)}
|
|
167
|
-
</div>
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## How to subscribe to state changes?
|
|
173
|
-
|
|
174
|
-
You can subscribe to state changes using the `subscribe` method of the store.
|
|
175
|
-
|
|
176
|
-
```tsx
|
|
177
|
-
function Component() {
|
|
178
|
-
...
|
|
179
|
-
useEffect(() => {
|
|
180
|
-
const unsubscribe = store.subscribe((state) => {
|
|
181
|
-
console.log(`State changed`, state);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return () => {
|
|
185
|
-
unsubscribe();
|
|
186
|
-
};
|
|
187
|
-
}, []);
|
|
188
|
-
|
|
189
|
-
...
|
|
190
|
-
}
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## How to update state manually?
|
|
194
|
-
|
|
195
|
-
You can update the state manually using the `dispatch` method of the store.
|
|
196
|
-
|
|
197
|
-
```tsx
|
|
198
|
-
function Component() {
|
|
199
|
-
...
|
|
200
|
-
const updateEmail = () => {
|
|
201
|
-
store.dispatch({ email: "ohjinsu98@icloud.com" });
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
return <button onClick={updateEmail}>Update Email</button>;
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
The `dispatch` method uses immerjs internally to update the state, so you can also use a function to update the state based on the previous state.
|
|
209
|
-
|
|
210
|
-
```tsx
|
|
211
|
-
function Component() {
|
|
212
|
-
...
|
|
213
|
-
|
|
214
|
-
const updateEmail = () => {
|
|
215
|
-
store.dispatch((state) => {
|
|
216
|
-
state.email = "ohjinsu98@icloud.com";
|
|
217
|
-
});
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
return <button onClick={updateEmail}>Update Email</button>;
|
|
221
|
-
}
|
|
222
|
-
```
|
|
3
|
+
A rich text editor component for React built on ProseMirror.
|
package/dist/attach_file.d.mts
CHANGED
|
@@ -23,6 +23,10 @@ type AttachFileOptions = {
|
|
|
23
23
|
alt?: string;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
+
declare const base64ImageUploader: (file: File) => Promise<{
|
|
27
|
+
src: string;
|
|
28
|
+
alt: string;
|
|
29
|
+
}>;
|
|
26
30
|
declare function createAttachFile({ schema, generateMetadata, uploadFile, }: AttachFileOptions): AttachFile;
|
|
27
31
|
|
|
28
|
-
export { type AttachFile, createAttachFile };
|
|
32
|
+
export { type AttachFile, base64ImageUploader, createAttachFile };
|
package/dist/attach_file.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ type AttachFileOptions = {
|
|
|
23
23
|
alt?: string;
|
|
24
24
|
};
|
|
25
25
|
};
|
|
26
|
+
declare const base64ImageUploader: (file: File) => Promise<{
|
|
27
|
+
src: string;
|
|
28
|
+
alt: string;
|
|
29
|
+
}>;
|
|
26
30
|
declare function createAttachFile({ schema, generateMetadata, uploadFile, }: AttachFileOptions): AttachFile;
|
|
27
31
|
|
|
28
|
-
export { type AttachFile, createAttachFile };
|
|
32
|
+
export { type AttachFile, base64ImageUploader, createAttachFile };
|
package/dist/attach_file.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/attach_file.tsx
|
|
21
21
|
var attach_file_exports = {};
|
|
22
22
|
__export(attach_file_exports, {
|
|
23
|
+
base64ImageUploader: () => base64ImageUploader,
|
|
23
24
|
createAttachFile: () => createAttachFile
|
|
24
25
|
});
|
|
25
26
|
module.exports = __toCommonJS(attach_file_exports);
|
|
@@ -91,15 +92,24 @@ var findPlaceholder = (state, id) => {
|
|
|
91
92
|
};
|
|
92
93
|
|
|
93
94
|
// src/attach_file.tsx
|
|
95
|
+
var base64ImageUploader = async (file) => {
|
|
96
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
97
|
+
const reader = new FileReader();
|
|
98
|
+
reader.onload = () => {
|
|
99
|
+
resolve(reader.result);
|
|
100
|
+
};
|
|
101
|
+
reader.onerror = reject;
|
|
102
|
+
reader.readAsDataURL(file);
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
src: base64,
|
|
106
|
+
alt: file.name
|
|
107
|
+
};
|
|
108
|
+
};
|
|
94
109
|
function createAttachFile({
|
|
95
110
|
schema,
|
|
96
111
|
generateMetadata,
|
|
97
|
-
uploadFile =
|
|
98
|
-
return {
|
|
99
|
-
src: URL.createObjectURL(file),
|
|
100
|
-
alt: file.name
|
|
101
|
-
};
|
|
102
|
-
}
|
|
112
|
+
uploadFile = base64ImageUploader
|
|
103
113
|
}) {
|
|
104
114
|
const attachEachFile = async (view, file, pos) => {
|
|
105
115
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -151,9 +161,7 @@ function createAttachFile({
|
|
|
151
161
|
}
|
|
152
162
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
153
163
|
} catch (e) {
|
|
154
|
-
view.dispatch(
|
|
155
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
156
|
-
);
|
|
164
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
157
165
|
}
|
|
158
166
|
};
|
|
159
167
|
return async (view, files, pos) => {
|
|
@@ -165,5 +173,6 @@ function createAttachFile({
|
|
|
165
173
|
}
|
|
166
174
|
// Annotate the CommonJS export names for ESM import in node:
|
|
167
175
|
0 && (module.exports = {
|
|
176
|
+
base64ImageUploader,
|
|
168
177
|
createAttachFile
|
|
169
178
|
});
|
package/dist/attach_file.mjs
CHANGED
|
@@ -67,15 +67,24 @@ var findPlaceholder = (state, id) => {
|
|
|
67
67
|
};
|
|
68
68
|
|
|
69
69
|
// src/attach_file.tsx
|
|
70
|
+
var base64ImageUploader = async (file) => {
|
|
71
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
72
|
+
const reader = new FileReader();
|
|
73
|
+
reader.onload = () => {
|
|
74
|
+
resolve(reader.result);
|
|
75
|
+
};
|
|
76
|
+
reader.onerror = reject;
|
|
77
|
+
reader.readAsDataURL(file);
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
src: base64,
|
|
81
|
+
alt: file.name
|
|
82
|
+
};
|
|
83
|
+
};
|
|
70
84
|
function createAttachFile({
|
|
71
85
|
schema,
|
|
72
86
|
generateMetadata,
|
|
73
|
-
uploadFile =
|
|
74
|
-
return {
|
|
75
|
-
src: URL.createObjectURL(file),
|
|
76
|
-
alt: file.name
|
|
77
|
-
};
|
|
78
|
-
}
|
|
87
|
+
uploadFile = base64ImageUploader
|
|
79
88
|
}) {
|
|
80
89
|
const attachEachFile = async (view, file, pos) => {
|
|
81
90
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -127,9 +136,7 @@ function createAttachFile({
|
|
|
127
136
|
}
|
|
128
137
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
129
138
|
} catch (e) {
|
|
130
|
-
view.dispatch(
|
|
131
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
132
|
-
);
|
|
139
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
133
140
|
}
|
|
134
141
|
};
|
|
135
142
|
return async (view, files, pos) => {
|
|
@@ -140,5 +147,6 @@ function createAttachFile({
|
|
|
140
147
|
};
|
|
141
148
|
}
|
|
142
149
|
export {
|
|
150
|
+
base64ImageUploader,
|
|
143
151
|
createAttachFile
|
|
144
152
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { TextEditorController, TextEditorProps, createTextEditor } from './text_editor.mjs';
|
|
2
2
|
export { createSchema } from './schema.mjs';
|
|
3
|
-
export { AttachFile, createAttachFile } from './attach_file.mjs';
|
|
3
|
+
export { AttachFile, base64ImageUploader, createAttachFile } from './attach_file.mjs';
|
|
4
4
|
import 'orderedmap';
|
|
5
5
|
import 'prosemirror-model';
|
|
6
6
|
import 'react';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { TextEditorController, TextEditorProps, createTextEditor } from './text_editor.js';
|
|
2
2
|
export { createSchema } from './schema.js';
|
|
3
|
-
export { AttachFile, createAttachFile } from './attach_file.js';
|
|
3
|
+
export { AttachFile, base64ImageUploader, createAttachFile } from './attach_file.js';
|
|
4
4
|
import 'orderedmap';
|
|
5
5
|
import 'prosemirror-model';
|
|
6
6
|
import 'react';
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
base64ImageUploader: () => base64ImageUploader,
|
|
33
34
|
createAttachFile: () => createAttachFile,
|
|
34
35
|
createSchema: () => createSchema,
|
|
35
36
|
createTextEditor: () => createTextEditor
|
|
@@ -472,15 +473,24 @@ function cn(...classes) {
|
|
|
472
473
|
|
|
473
474
|
// src/attach_file.tsx
|
|
474
475
|
var import_prosemirror_view3 = require("prosemirror-view");
|
|
476
|
+
var base64ImageUploader = async (file) => {
|
|
477
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
478
|
+
const reader = new FileReader();
|
|
479
|
+
reader.onload = () => {
|
|
480
|
+
resolve(reader.result);
|
|
481
|
+
};
|
|
482
|
+
reader.onerror = reject;
|
|
483
|
+
reader.readAsDataURL(file);
|
|
484
|
+
});
|
|
485
|
+
return {
|
|
486
|
+
src: base64,
|
|
487
|
+
alt: file.name
|
|
488
|
+
};
|
|
489
|
+
};
|
|
475
490
|
function createAttachFile({
|
|
476
491
|
schema,
|
|
477
492
|
generateMetadata,
|
|
478
|
-
uploadFile =
|
|
479
|
-
return {
|
|
480
|
-
src: URL.createObjectURL(file),
|
|
481
|
-
alt: file.name
|
|
482
|
-
};
|
|
483
|
-
}
|
|
493
|
+
uploadFile = base64ImageUploader
|
|
484
494
|
}) {
|
|
485
495
|
const attachEachFile = async (view, file, pos) => {
|
|
486
496
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -532,9 +542,7 @@ function createAttachFile({
|
|
|
532
542
|
}
|
|
533
543
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
534
544
|
} catch (e) {
|
|
535
|
-
view.dispatch(
|
|
536
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
537
|
-
);
|
|
545
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
538
546
|
}
|
|
539
547
|
};
|
|
540
548
|
return async (view, files, pos) => {
|
|
@@ -573,12 +581,9 @@ function createTextEditor(options = {}) {
|
|
|
573
581
|
} = {}) {
|
|
574
582
|
const containerRef = (0, import_react2.useRef)(null);
|
|
575
583
|
const inputRef = (0, import_react2.useRef)(null);
|
|
576
|
-
(0, import_react2.
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
const subject = new import_rxjs.Subject();
|
|
584
|
+
const controllerRef = (0, import_react2.useRef)(null);
|
|
585
|
+
const subject = (0, import_react.useMemo)(() => new import_rxjs.Subject(), []);
|
|
586
|
+
(0, import_react.useImperativeHandle)(ref, () => {
|
|
582
587
|
const wrapper = document.createElement("div");
|
|
583
588
|
const toInnerHTML = (value) => {
|
|
584
589
|
if (mode === "html") {
|
|
@@ -586,10 +591,8 @@ function createTextEditor(options = {}) {
|
|
|
586
591
|
}
|
|
587
592
|
return value.split("\n").map((line) => `<p>${line}</p>`).join("");
|
|
588
593
|
};
|
|
589
|
-
wrapper.innerHTML = toInnerHTML(
|
|
590
|
-
|
|
591
|
-
);
|
|
592
|
-
const view = new import_prosemirror_view4.EditorView(element, {
|
|
594
|
+
wrapper.innerHTML = toInnerHTML(defaultValue ? String(defaultValue) : "");
|
|
595
|
+
const view = new import_prosemirror_view4.EditorView(containerRef.current, {
|
|
593
596
|
...editor,
|
|
594
597
|
attributes: (state2) => {
|
|
595
598
|
const propsAttributes = (() => {
|
|
@@ -664,27 +667,11 @@ function createTextEditor(options = {}) {
|
|
|
664
667
|
const state2 = view.state;
|
|
665
668
|
return state2.doc.textBetween(0, state2.doc.content.size, "\n");
|
|
666
669
|
}
|
|
667
|
-
const sub = subject.pipe(
|
|
668
|
-
(0, import_rxjs.filter)((tr) => tr.docChanged),
|
|
669
|
-
(0, import_rxjs.debounceTime)(updateDelay)
|
|
670
|
-
).subscribe(() => {
|
|
671
|
-
if (inputRef.current) {
|
|
672
|
-
switch (mode) {
|
|
673
|
-
case "text":
|
|
674
|
-
inputRef.current.value = toTextContent();
|
|
675
|
-
break;
|
|
676
|
-
default:
|
|
677
|
-
inputRef.current.value = toHTML();
|
|
678
|
-
break;
|
|
679
|
-
}
|
|
680
|
-
const event = new Event("input", { bubbles: true });
|
|
681
|
-
inputRef.current.dispatchEvent(event);
|
|
682
|
-
}
|
|
683
|
-
});
|
|
684
670
|
if (autoFocus) {
|
|
685
671
|
view.focus();
|
|
686
672
|
}
|
|
687
673
|
const textEditorController = {
|
|
674
|
+
schema,
|
|
688
675
|
view,
|
|
689
676
|
subject,
|
|
690
677
|
set value(value) {
|
|
@@ -700,26 +687,33 @@ function createTextEditor(options = {}) {
|
|
|
700
687
|
},
|
|
701
688
|
clear
|
|
702
689
|
};
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
690
|
+
controllerRef.current = textEditorController;
|
|
691
|
+
return textEditorController;
|
|
692
|
+
});
|
|
693
|
+
(0, import_react2.useEffect)(() => {
|
|
694
|
+
const controller = controllerRef.current;
|
|
695
|
+
if (!controller) {
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
const sub = controller.subject.pipe(
|
|
699
|
+
(0, import_rxjs.filter)((tr) => tr.docChanged),
|
|
700
|
+
(0, import_rxjs.debounceTime)(updateDelay)
|
|
701
|
+
).subscribe(() => {
|
|
702
|
+
if (inputRef.current) {
|
|
703
|
+
inputRef.current.value = controller.value;
|
|
704
|
+
const event = new Event("input", { bubbles: true });
|
|
705
|
+
inputRef.current.dispatchEvent(event);
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
if (autoFocus) {
|
|
709
|
+
controller.view.focus();
|
|
707
710
|
}
|
|
708
711
|
return () => {
|
|
709
712
|
sub.unsubscribe();
|
|
710
|
-
view.destroy();
|
|
711
|
-
element.innerHTML = "";
|
|
713
|
+
controller.view.destroy();
|
|
712
714
|
};
|
|
713
715
|
}, []);
|
|
714
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ import_react.default.createElement(
|
|
715
|
-
"input",
|
|
716
|
-
{
|
|
717
|
-
ref: inputRef,
|
|
718
|
-
type: "hidden",
|
|
719
|
-
name,
|
|
720
|
-
onInput: onChange
|
|
721
|
-
}
|
|
722
|
-
));
|
|
716
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ import_react.default.createElement("input", { ref: inputRef, type: "hidden", name, onInput: onChange }));
|
|
723
717
|
}
|
|
724
718
|
return {
|
|
725
719
|
schema,
|
|
@@ -729,6 +723,7 @@ function createTextEditor(options = {}) {
|
|
|
729
723
|
}
|
|
730
724
|
// Annotate the CommonJS export names for ESM import in node:
|
|
731
725
|
0 && (module.exports = {
|
|
726
|
+
base64ImageUploader,
|
|
732
727
|
createAttachFile,
|
|
733
728
|
createSchema,
|
|
734
729
|
createTextEditor
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// src/text_editor.tsx
|
|
2
|
-
import React
|
|
2
|
+
import React, {
|
|
3
|
+
useImperativeHandle,
|
|
4
|
+
useMemo
|
|
5
|
+
} from "react";
|
|
3
6
|
import {
|
|
4
7
|
EditorState as EditorState2
|
|
5
8
|
} from "prosemirror-state";
|
|
@@ -436,15 +439,24 @@ function cn(...classes) {
|
|
|
436
439
|
|
|
437
440
|
// src/attach_file.tsx
|
|
438
441
|
import "prosemirror-view";
|
|
442
|
+
var base64ImageUploader = async (file) => {
|
|
443
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
444
|
+
const reader = new FileReader();
|
|
445
|
+
reader.onload = () => {
|
|
446
|
+
resolve(reader.result);
|
|
447
|
+
};
|
|
448
|
+
reader.onerror = reject;
|
|
449
|
+
reader.readAsDataURL(file);
|
|
450
|
+
});
|
|
451
|
+
return {
|
|
452
|
+
src: base64,
|
|
453
|
+
alt: file.name
|
|
454
|
+
};
|
|
455
|
+
};
|
|
439
456
|
function createAttachFile({
|
|
440
457
|
schema,
|
|
441
458
|
generateMetadata,
|
|
442
|
-
uploadFile =
|
|
443
|
-
return {
|
|
444
|
-
src: URL.createObjectURL(file),
|
|
445
|
-
alt: file.name
|
|
446
|
-
};
|
|
447
|
-
}
|
|
459
|
+
uploadFile = base64ImageUploader
|
|
448
460
|
}) {
|
|
449
461
|
const attachEachFile = async (view, file, pos) => {
|
|
450
462
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -496,9 +508,7 @@ function createAttachFile({
|
|
|
496
508
|
}
|
|
497
509
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
498
510
|
} catch (e) {
|
|
499
|
-
view.dispatch(
|
|
500
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
501
|
-
);
|
|
511
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
502
512
|
}
|
|
503
513
|
};
|
|
504
514
|
return async (view, files, pos) => {
|
|
@@ -537,12 +547,9 @@ function createTextEditor(options = {}) {
|
|
|
537
547
|
} = {}) {
|
|
538
548
|
const containerRef = useRef(null);
|
|
539
549
|
const inputRef = useRef(null);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
const subject = new Subject();
|
|
550
|
+
const controllerRef = useRef(null);
|
|
551
|
+
const subject = useMemo(() => new Subject(), []);
|
|
552
|
+
useImperativeHandle(ref, () => {
|
|
546
553
|
const wrapper = document.createElement("div");
|
|
547
554
|
const toInnerHTML = (value) => {
|
|
548
555
|
if (mode === "html") {
|
|
@@ -550,10 +557,8 @@ function createTextEditor(options = {}) {
|
|
|
550
557
|
}
|
|
551
558
|
return value.split("\n").map((line) => `<p>${line}</p>`).join("");
|
|
552
559
|
};
|
|
553
|
-
wrapper.innerHTML = toInnerHTML(
|
|
554
|
-
|
|
555
|
-
);
|
|
556
|
-
const view = new EditorView3(element, {
|
|
560
|
+
wrapper.innerHTML = toInnerHTML(defaultValue ? String(defaultValue) : "");
|
|
561
|
+
const view = new EditorView3(containerRef.current, {
|
|
557
562
|
...editor,
|
|
558
563
|
attributes: (state2) => {
|
|
559
564
|
const propsAttributes = (() => {
|
|
@@ -628,27 +633,11 @@ function createTextEditor(options = {}) {
|
|
|
628
633
|
const state2 = view.state;
|
|
629
634
|
return state2.doc.textBetween(0, state2.doc.content.size, "\n");
|
|
630
635
|
}
|
|
631
|
-
const sub = subject.pipe(
|
|
632
|
-
filter((tr) => tr.docChanged),
|
|
633
|
-
debounceTime(updateDelay)
|
|
634
|
-
).subscribe(() => {
|
|
635
|
-
if (inputRef.current) {
|
|
636
|
-
switch (mode) {
|
|
637
|
-
case "text":
|
|
638
|
-
inputRef.current.value = toTextContent();
|
|
639
|
-
break;
|
|
640
|
-
default:
|
|
641
|
-
inputRef.current.value = toHTML();
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
const event = new Event("input", { bubbles: true });
|
|
645
|
-
inputRef.current.dispatchEvent(event);
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
636
|
if (autoFocus) {
|
|
649
637
|
view.focus();
|
|
650
638
|
}
|
|
651
639
|
const textEditorController = {
|
|
640
|
+
schema,
|
|
652
641
|
view,
|
|
653
642
|
subject,
|
|
654
643
|
set value(value) {
|
|
@@ -664,26 +653,33 @@ function createTextEditor(options = {}) {
|
|
|
664
653
|
},
|
|
665
654
|
clear
|
|
666
655
|
};
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
656
|
+
controllerRef.current = textEditorController;
|
|
657
|
+
return textEditorController;
|
|
658
|
+
});
|
|
659
|
+
useEffect(() => {
|
|
660
|
+
const controller = controllerRef.current;
|
|
661
|
+
if (!controller) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const sub = controller.subject.pipe(
|
|
665
|
+
filter((tr) => tr.docChanged),
|
|
666
|
+
debounceTime(updateDelay)
|
|
667
|
+
).subscribe(() => {
|
|
668
|
+
if (inputRef.current) {
|
|
669
|
+
inputRef.current.value = controller.value;
|
|
670
|
+
const event = new Event("input", { bubbles: true });
|
|
671
|
+
inputRef.current.dispatchEvent(event);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
if (autoFocus) {
|
|
675
|
+
controller.view.focus();
|
|
671
676
|
}
|
|
672
677
|
return () => {
|
|
673
678
|
sub.unsubscribe();
|
|
674
|
-
view.destroy();
|
|
675
|
-
element.innerHTML = "";
|
|
679
|
+
controller.view.destroy();
|
|
676
680
|
};
|
|
677
681
|
}, []);
|
|
678
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ React.createElement(
|
|
679
|
-
"input",
|
|
680
|
-
{
|
|
681
|
-
ref: inputRef,
|
|
682
|
-
type: "hidden",
|
|
683
|
-
name,
|
|
684
|
-
onInput: onChange
|
|
685
|
-
}
|
|
686
|
-
));
|
|
682
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ React.createElement("input", { ref: inputRef, type: "hidden", name, onInput: onChange }));
|
|
687
683
|
}
|
|
688
684
|
return {
|
|
689
685
|
schema,
|
|
@@ -692,6 +688,7 @@ function createTextEditor(options = {}) {
|
|
|
692
688
|
};
|
|
693
689
|
}
|
|
694
690
|
export {
|
|
691
|
+
base64ImageUploader,
|
|
695
692
|
createAttachFile,
|
|
696
693
|
createSchema,
|
|
697
694
|
createTextEditor
|
package/dist/text_editor.d.mts
CHANGED
|
@@ -4,10 +4,11 @@ import * as prosemirror_model from 'prosemirror-model';
|
|
|
4
4
|
import React, { DetailedHTMLProps, InputHTMLAttributes, Ref } from 'react';
|
|
5
5
|
import { Transaction, EditorStateConfig } from 'prosemirror-state';
|
|
6
6
|
import { EditorView, DirectEditorProps } from 'prosemirror-view';
|
|
7
|
+
import { createSchema } from './schema.mjs';
|
|
7
8
|
import { Subject } from 'rxjs';
|
|
8
|
-
import './schema.mjs';
|
|
9
9
|
|
|
10
10
|
type TextEditorController = {
|
|
11
|
+
schema: ReturnType<typeof createSchema>;
|
|
11
12
|
view: EditorView;
|
|
12
13
|
subject: Subject<Transaction>;
|
|
13
14
|
set value(value: string);
|
package/dist/text_editor.d.ts
CHANGED
|
@@ -4,10 +4,11 @@ import * as prosemirror_model from 'prosemirror-model';
|
|
|
4
4
|
import React, { DetailedHTMLProps, InputHTMLAttributes, Ref } from 'react';
|
|
5
5
|
import { Transaction, EditorStateConfig } from 'prosemirror-state';
|
|
6
6
|
import { EditorView, DirectEditorProps } from 'prosemirror-view';
|
|
7
|
+
import { createSchema } from './schema.js';
|
|
7
8
|
import { Subject } from 'rxjs';
|
|
8
|
-
import './schema.js';
|
|
9
9
|
|
|
10
10
|
type TextEditorController = {
|
|
11
|
+
schema: ReturnType<typeof createSchema>;
|
|
11
12
|
view: EditorView;
|
|
12
13
|
subject: Subject<Transaction>;
|
|
13
14
|
set value(value: string);
|
package/dist/text_editor.js
CHANGED
|
@@ -468,15 +468,24 @@ function cn(...classes) {
|
|
|
468
468
|
|
|
469
469
|
// src/attach_file.tsx
|
|
470
470
|
var import_prosemirror_view3 = require("prosemirror-view");
|
|
471
|
+
var base64ImageUploader = async (file) => {
|
|
472
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
473
|
+
const reader = new FileReader();
|
|
474
|
+
reader.onload = () => {
|
|
475
|
+
resolve(reader.result);
|
|
476
|
+
};
|
|
477
|
+
reader.onerror = reject;
|
|
478
|
+
reader.readAsDataURL(file);
|
|
479
|
+
});
|
|
480
|
+
return {
|
|
481
|
+
src: base64,
|
|
482
|
+
alt: file.name
|
|
483
|
+
};
|
|
484
|
+
};
|
|
471
485
|
function createAttachFile({
|
|
472
486
|
schema,
|
|
473
487
|
generateMetadata,
|
|
474
|
-
uploadFile =
|
|
475
|
-
return {
|
|
476
|
-
src: URL.createObjectURL(file),
|
|
477
|
-
alt: file.name
|
|
478
|
-
};
|
|
479
|
-
}
|
|
488
|
+
uploadFile = base64ImageUploader
|
|
480
489
|
}) {
|
|
481
490
|
const attachEachFile = async (view, file, pos) => {
|
|
482
491
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -528,9 +537,7 @@ function createAttachFile({
|
|
|
528
537
|
}
|
|
529
538
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
530
539
|
} catch (e) {
|
|
531
|
-
view.dispatch(
|
|
532
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
533
|
-
);
|
|
540
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
534
541
|
}
|
|
535
542
|
};
|
|
536
543
|
return async (view, files, pos) => {
|
|
@@ -569,12 +576,9 @@ function createTextEditor(options = {}) {
|
|
|
569
576
|
} = {}) {
|
|
570
577
|
const containerRef = (0, import_react2.useRef)(null);
|
|
571
578
|
const inputRef = (0, import_react2.useRef)(null);
|
|
572
|
-
(0, import_react2.
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
return;
|
|
576
|
-
}
|
|
577
|
-
const subject = new import_rxjs.Subject();
|
|
579
|
+
const controllerRef = (0, import_react2.useRef)(null);
|
|
580
|
+
const subject = (0, import_react.useMemo)(() => new import_rxjs.Subject(), []);
|
|
581
|
+
(0, import_react.useImperativeHandle)(ref, () => {
|
|
578
582
|
const wrapper = document.createElement("div");
|
|
579
583
|
const toInnerHTML = (value) => {
|
|
580
584
|
if (mode === "html") {
|
|
@@ -582,10 +586,8 @@ function createTextEditor(options = {}) {
|
|
|
582
586
|
}
|
|
583
587
|
return value.split("\n").map((line) => `<p>${line}</p>`).join("");
|
|
584
588
|
};
|
|
585
|
-
wrapper.innerHTML = toInnerHTML(
|
|
586
|
-
|
|
587
|
-
);
|
|
588
|
-
const view = new import_prosemirror_view4.EditorView(element, {
|
|
589
|
+
wrapper.innerHTML = toInnerHTML(defaultValue ? String(defaultValue) : "");
|
|
590
|
+
const view = new import_prosemirror_view4.EditorView(containerRef.current, {
|
|
589
591
|
...editor,
|
|
590
592
|
attributes: (state2) => {
|
|
591
593
|
const propsAttributes = (() => {
|
|
@@ -660,27 +662,11 @@ function createTextEditor(options = {}) {
|
|
|
660
662
|
const state2 = view.state;
|
|
661
663
|
return state2.doc.textBetween(0, state2.doc.content.size, "\n");
|
|
662
664
|
}
|
|
663
|
-
const sub = subject.pipe(
|
|
664
|
-
(0, import_rxjs.filter)((tr) => tr.docChanged),
|
|
665
|
-
(0, import_rxjs.debounceTime)(updateDelay)
|
|
666
|
-
).subscribe(() => {
|
|
667
|
-
if (inputRef.current) {
|
|
668
|
-
switch (mode) {
|
|
669
|
-
case "text":
|
|
670
|
-
inputRef.current.value = toTextContent();
|
|
671
|
-
break;
|
|
672
|
-
default:
|
|
673
|
-
inputRef.current.value = toHTML();
|
|
674
|
-
break;
|
|
675
|
-
}
|
|
676
|
-
const event = new Event("input", { bubbles: true });
|
|
677
|
-
inputRef.current.dispatchEvent(event);
|
|
678
|
-
}
|
|
679
|
-
});
|
|
680
665
|
if (autoFocus) {
|
|
681
666
|
view.focus();
|
|
682
667
|
}
|
|
683
668
|
const textEditorController = {
|
|
669
|
+
schema,
|
|
684
670
|
view,
|
|
685
671
|
subject,
|
|
686
672
|
set value(value) {
|
|
@@ -696,26 +682,33 @@ function createTextEditor(options = {}) {
|
|
|
696
682
|
},
|
|
697
683
|
clear
|
|
698
684
|
};
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
685
|
+
controllerRef.current = textEditorController;
|
|
686
|
+
return textEditorController;
|
|
687
|
+
});
|
|
688
|
+
(0, import_react2.useEffect)(() => {
|
|
689
|
+
const controller = controllerRef.current;
|
|
690
|
+
if (!controller) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
const sub = controller.subject.pipe(
|
|
694
|
+
(0, import_rxjs.filter)((tr) => tr.docChanged),
|
|
695
|
+
(0, import_rxjs.debounceTime)(updateDelay)
|
|
696
|
+
).subscribe(() => {
|
|
697
|
+
if (inputRef.current) {
|
|
698
|
+
inputRef.current.value = controller.value;
|
|
699
|
+
const event = new Event("input", { bubbles: true });
|
|
700
|
+
inputRef.current.dispatchEvent(event);
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
if (autoFocus) {
|
|
704
|
+
controller.view.focus();
|
|
703
705
|
}
|
|
704
706
|
return () => {
|
|
705
707
|
sub.unsubscribe();
|
|
706
|
-
view.destroy();
|
|
707
|
-
element.innerHTML = "";
|
|
708
|
+
controller.view.destroy();
|
|
708
709
|
};
|
|
709
710
|
}, []);
|
|
710
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ import_react.default.createElement(
|
|
711
|
-
"input",
|
|
712
|
-
{
|
|
713
|
-
ref: inputRef,
|
|
714
|
-
type: "hidden",
|
|
715
|
-
name,
|
|
716
|
-
onInput: onChange
|
|
717
|
-
}
|
|
718
|
-
));
|
|
711
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ import_react.default.createElement("input", { ref: inputRef, type: "hidden", name, onInput: onChange }));
|
|
719
712
|
}
|
|
720
713
|
return {
|
|
721
714
|
schema,
|
package/dist/text_editor.mjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// src/text_editor.tsx
|
|
2
|
-
import React
|
|
2
|
+
import React, {
|
|
3
|
+
useImperativeHandle,
|
|
4
|
+
useMemo
|
|
5
|
+
} from "react";
|
|
3
6
|
import {
|
|
4
7
|
EditorState as EditorState2
|
|
5
8
|
} from "prosemirror-state";
|
|
@@ -436,15 +439,24 @@ function cn(...classes) {
|
|
|
436
439
|
|
|
437
440
|
// src/attach_file.tsx
|
|
438
441
|
import "prosemirror-view";
|
|
442
|
+
var base64ImageUploader = async (file) => {
|
|
443
|
+
const base64 = await new Promise((resolve, reject) => {
|
|
444
|
+
const reader = new FileReader();
|
|
445
|
+
reader.onload = () => {
|
|
446
|
+
resolve(reader.result);
|
|
447
|
+
};
|
|
448
|
+
reader.onerror = reject;
|
|
449
|
+
reader.readAsDataURL(file);
|
|
450
|
+
});
|
|
451
|
+
return {
|
|
452
|
+
src: base64,
|
|
453
|
+
alt: file.name
|
|
454
|
+
};
|
|
455
|
+
};
|
|
439
456
|
function createAttachFile({
|
|
440
457
|
schema,
|
|
441
458
|
generateMetadata,
|
|
442
|
-
uploadFile =
|
|
443
|
-
return {
|
|
444
|
-
src: URL.createObjectURL(file),
|
|
445
|
-
alt: file.name
|
|
446
|
-
};
|
|
447
|
-
}
|
|
459
|
+
uploadFile = base64ImageUploader
|
|
448
460
|
}) {
|
|
449
461
|
const attachEachFile = async (view, file, pos) => {
|
|
450
462
|
const metadata = generateMetadata ? await generateMetadata(file) : {};
|
|
@@ -496,9 +508,7 @@ function createAttachFile({
|
|
|
496
508
|
}
|
|
497
509
|
view.dispatch(tr2.replaceWith($pos, $pos, node));
|
|
498
510
|
} catch (e) {
|
|
499
|
-
view.dispatch(
|
|
500
|
-
tr.setMeta(uploadPlaceholderPlugin, { remove: { id } })
|
|
501
|
-
);
|
|
511
|
+
view.dispatch(tr.setMeta(uploadPlaceholderPlugin, { remove: { id } }));
|
|
502
512
|
}
|
|
503
513
|
};
|
|
504
514
|
return async (view, files, pos) => {
|
|
@@ -537,12 +547,9 @@ function createTextEditor(options = {}) {
|
|
|
537
547
|
} = {}) {
|
|
538
548
|
const containerRef = useRef(null);
|
|
539
549
|
const inputRef = useRef(null);
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
const subject = new Subject();
|
|
550
|
+
const controllerRef = useRef(null);
|
|
551
|
+
const subject = useMemo(() => new Subject(), []);
|
|
552
|
+
useImperativeHandle(ref, () => {
|
|
546
553
|
const wrapper = document.createElement("div");
|
|
547
554
|
const toInnerHTML = (value) => {
|
|
548
555
|
if (mode === "html") {
|
|
@@ -550,10 +557,8 @@ function createTextEditor(options = {}) {
|
|
|
550
557
|
}
|
|
551
558
|
return value.split("\n").map((line) => `<p>${line}</p>`).join("");
|
|
552
559
|
};
|
|
553
|
-
wrapper.innerHTML = toInnerHTML(
|
|
554
|
-
|
|
555
|
-
);
|
|
556
|
-
const view = new EditorView3(element, {
|
|
560
|
+
wrapper.innerHTML = toInnerHTML(defaultValue ? String(defaultValue) : "");
|
|
561
|
+
const view = new EditorView3(containerRef.current, {
|
|
557
562
|
...editor,
|
|
558
563
|
attributes: (state2) => {
|
|
559
564
|
const propsAttributes = (() => {
|
|
@@ -628,27 +633,11 @@ function createTextEditor(options = {}) {
|
|
|
628
633
|
const state2 = view.state;
|
|
629
634
|
return state2.doc.textBetween(0, state2.doc.content.size, "\n");
|
|
630
635
|
}
|
|
631
|
-
const sub = subject.pipe(
|
|
632
|
-
filter((tr) => tr.docChanged),
|
|
633
|
-
debounceTime(updateDelay)
|
|
634
|
-
).subscribe(() => {
|
|
635
|
-
if (inputRef.current) {
|
|
636
|
-
switch (mode) {
|
|
637
|
-
case "text":
|
|
638
|
-
inputRef.current.value = toTextContent();
|
|
639
|
-
break;
|
|
640
|
-
default:
|
|
641
|
-
inputRef.current.value = toHTML();
|
|
642
|
-
break;
|
|
643
|
-
}
|
|
644
|
-
const event = new Event("input", { bubbles: true });
|
|
645
|
-
inputRef.current.dispatchEvent(event);
|
|
646
|
-
}
|
|
647
|
-
});
|
|
648
636
|
if (autoFocus) {
|
|
649
637
|
view.focus();
|
|
650
638
|
}
|
|
651
639
|
const textEditorController = {
|
|
640
|
+
schema,
|
|
652
641
|
view,
|
|
653
642
|
subject,
|
|
654
643
|
set value(value) {
|
|
@@ -664,26 +653,33 @@ function createTextEditor(options = {}) {
|
|
|
664
653
|
},
|
|
665
654
|
clear
|
|
666
655
|
};
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
656
|
+
controllerRef.current = textEditorController;
|
|
657
|
+
return textEditorController;
|
|
658
|
+
});
|
|
659
|
+
useEffect(() => {
|
|
660
|
+
const controller = controllerRef.current;
|
|
661
|
+
if (!controller) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const sub = controller.subject.pipe(
|
|
665
|
+
filter((tr) => tr.docChanged),
|
|
666
|
+
debounceTime(updateDelay)
|
|
667
|
+
).subscribe(() => {
|
|
668
|
+
if (inputRef.current) {
|
|
669
|
+
inputRef.current.value = controller.value;
|
|
670
|
+
const event = new Event("input", { bubbles: true });
|
|
671
|
+
inputRef.current.dispatchEvent(event);
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
if (autoFocus) {
|
|
675
|
+
controller.view.focus();
|
|
671
676
|
}
|
|
672
677
|
return () => {
|
|
673
678
|
sub.unsubscribe();
|
|
674
|
-
view.destroy();
|
|
675
|
-
element.innerHTML = "";
|
|
679
|
+
controller.view.destroy();
|
|
676
680
|
};
|
|
677
681
|
}, []);
|
|
678
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ React.createElement(
|
|
679
|
-
"input",
|
|
680
|
-
{
|
|
681
|
-
ref: inputRef,
|
|
682
|
-
type: "hidden",
|
|
683
|
-
name,
|
|
684
|
-
onInput: onChange
|
|
685
|
-
}
|
|
686
|
-
));
|
|
682
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { ref: containerRef, className: container, ...props }), /* @__PURE__ */ React.createElement("input", { ref: inputRef, type: "hidden", name, onInput: onChange }));
|
|
687
683
|
}
|
|
688
684
|
return {
|
|
689
685
|
schema,
|
package/package.json
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
"./prosemirror": {
|
|
15
|
-
"types": "./dist/prosemirror/index.d.ts",
|
|
16
|
-
"import": "./dist/prosemirror/index.mjs",
|
|
17
|
-
"require": "./dist/prosemirror/index.js"
|
|
18
|
-
}
|
|
2
|
+
"name": "dn-react-text-editor",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"types": "./dist/index.d.ts",
|
|
5
|
+
"main": "./dist/index.mjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
19
13
|
},
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "git+https://github.com/dndnsoft/dn-react-text-editor.git"
|
|
27
|
-
},
|
|
28
|
-
"author": "",
|
|
29
|
-
"license": "MIT",
|
|
30
|
-
"bugs": {
|
|
31
|
-
"url": "https://github.com/dndnsoft/dn-react-text-editor/issues"
|
|
32
|
-
},
|
|
33
|
-
"homepage": "https://github.com/dndnsoft/dn-react-text-editor#readme",
|
|
34
|
-
"description": "",
|
|
35
|
-
"devDependencies": {
|
|
36
|
-
"@types/node": "^24.10.1",
|
|
37
|
-
"@types/react": "^19",
|
|
38
|
-
"@types/react-dom": "^19",
|
|
39
|
-
"tsup": "^8.5.1",
|
|
40
|
-
"typescript": "^5.7.3"
|
|
41
|
-
},
|
|
42
|
-
"peerDependencies": {
|
|
43
|
-
"react": "^19",
|
|
44
|
-
"react-dom": "^19"
|
|
45
|
-
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"prosemirror-commands": "^1.7.1",
|
|
48
|
-
"prosemirror-history": "^1.5.0",
|
|
49
|
-
"prosemirror-keymap": "^1.2.3",
|
|
50
|
-
"prosemirror-model": "^1.25.4",
|
|
51
|
-
"prosemirror-schema-list": "^1.5.1",
|
|
52
|
-
"prosemirror-state": "^1.4.4",
|
|
53
|
-
"prosemirror-view": "^1.41.3",
|
|
54
|
-
"rxjs": "^7.8.2"
|
|
14
|
+
"./prosemirror": {
|
|
15
|
+
"types": "./dist/prosemirror/index.d.ts",
|
|
16
|
+
"import": "./dist/prosemirror/index.mjs",
|
|
17
|
+
"require": "./dist/prosemirror/index.js"
|
|
55
18
|
}
|
|
56
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "NODE_OPTIONS='--max-old-space-size=16384' tsup",
|
|
22
|
+
"dev": "tsup --watch"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/dndnsoft/dn-react-text-editor.git"
|
|
27
|
+
},
|
|
28
|
+
"author": "",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/dndnsoft/dn-react-text-editor/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/dndnsoft/dn-react-text-editor#readme",
|
|
34
|
+
"description": "",
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^24.10.1",
|
|
37
|
+
"@types/react": "^19",
|
|
38
|
+
"@types/react-dom": "^19",
|
|
39
|
+
"tsup": "^8.5.1",
|
|
40
|
+
"typescript": "^5.7.3"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"react": "^19",
|
|
44
|
+
"react-dom": "^19"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"prosemirror-commands": "^1.7.1",
|
|
48
|
+
"prosemirror-history": "^1.5.0",
|
|
49
|
+
"prosemirror-keymap": "^1.2.3",
|
|
50
|
+
"prosemirror-model": "^1.25.4",
|
|
51
|
+
"prosemirror-schema-list": "^1.5.1",
|
|
52
|
+
"prosemirror-state": "^1.4.4",
|
|
53
|
+
"prosemirror-view": "^1.41.3",
|
|
54
|
+
"rxjs": "^7.8.2"
|
|
55
|
+
}
|
|
56
|
+
}
|