@handlewithcare/react-prosemirror 2.5.2 → 2.5.4
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 -3
- package/dist/cjs/ReactEditorView.js +36 -0
- package/dist/cjs/components/CustomNodeView.js +11 -23
- package/dist/cjs/components/ReactNodeView.js +16 -18
- package/dist/cjs/hooks/useEditor.js +19 -17
- package/dist/cjs/hooks/useEffectEvent.js +34 -0
- package/dist/cjs/hooks/useNodeViewDescriptor.js +16 -24
- package/dist/esm/ReactEditorView.js +36 -0
- package/dist/esm/components/CustomNodeView.js +12 -24
- package/dist/esm/components/ReactNodeView.js +16 -18
- package/dist/esm/hooks/useEditor.js +19 -17
- package/dist/esm/hooks/useEffectEvent.js +24 -0
- package/dist/esm/hooks/useNodeViewDescriptor.js +17 -25
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ReactEditorView.d.ts +13 -0
- package/dist/types/hooks/useEffectEvent.d.ts +1 -0
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { EMPTY_STATE } from "../constants.js";
|
|
|
6
6
|
import { beforeInputPlugin } from "../plugins/beforeInputPlugin.js";
|
|
7
7
|
import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
|
|
8
8
|
import { useComponentEventListeners } from "./useComponentEventListeners.js";
|
|
9
|
+
import { useEffectEvent } from "./useEffectEvent.js";
|
|
9
10
|
import { useForceUpdate } from "./useForceUpdate.js";
|
|
10
11
|
let didWarnValueDefaultValue = false;
|
|
11
12
|
/**
|
|
@@ -75,30 +76,31 @@ let didWarnValueDefaultValue = false;
|
|
|
75
76
|
const [view, setView] = useState(()=>{
|
|
76
77
|
return new StaticEditorView(directEditorProps);
|
|
77
78
|
});
|
|
79
|
+
const createEditorView = useEffectEvent((mount)=>{
|
|
80
|
+
if (mount) {
|
|
81
|
+
const view = new ReactEditorView({
|
|
82
|
+
mount
|
|
83
|
+
}, directEditorProps);
|
|
84
|
+
view.dom.addEventListener("compositionend", forceUpdate);
|
|
85
|
+
return view;
|
|
86
|
+
}
|
|
87
|
+
return new StaticEditorView(directEditorProps);
|
|
88
|
+
});
|
|
78
89
|
useClientLayoutEffect(()=>{
|
|
90
|
+
const view = createEditorView(mount);
|
|
91
|
+
setView(view);
|
|
79
92
|
return ()=>{
|
|
80
93
|
view.destroy();
|
|
81
94
|
};
|
|
82
95
|
}, [
|
|
83
|
-
|
|
96
|
+
createEditorView,
|
|
97
|
+
mount
|
|
84
98
|
]);
|
|
85
|
-
// This rule is concerned about infinite updates due to the
|
|
86
|
-
// call to setView. These calls are deliberately conditional,
|
|
87
|
-
// so this is not a concern.
|
|
88
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
99
|
useClientLayoutEffect(()=>{
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}, directEditorProps);
|
|
95
|
-
view.dom.addEventListener("compositionend", forceUpdate);
|
|
96
|
-
setView(view);
|
|
97
|
-
} else {
|
|
98
|
-
const view = new StaticEditorView(directEditorProps);
|
|
99
|
-
setView(view);
|
|
100
|
-
}
|
|
101
|
-
} else if (view instanceof ReactEditorView) {
|
|
100
|
+
// Ensure that the EditorView hasn't been destroyed before
|
|
101
|
+
// running effects. Running effects will reattach selection
|
|
102
|
+
// change listeners if the EditorView has been destroyed.
|
|
103
|
+
if (view instanceof ReactEditorView && !view.isDestroyed) {
|
|
102
104
|
view.commitPendingEffects();
|
|
103
105
|
}
|
|
104
106
|
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useCallback, useLayoutEffect, useRef } from "react";
|
|
2
|
+
export function useEffectEvent(fn) {
|
|
3
|
+
const ref = useRef(fn);
|
|
4
|
+
// Ideally this would be a useInsertionEffect, but
|
|
5
|
+
// that was introduced in React 18 and we still
|
|
6
|
+
// support React 17. useLayoutEffect is safe
|
|
7
|
+
// here as long as the function returned by
|
|
8
|
+
// useEffectEvent isn't called in a layout effect
|
|
9
|
+
// that's defined _before_ the useEffectEvent
|
|
10
|
+
// call, and effect events are never passed
|
|
11
|
+
// to child components.
|
|
12
|
+
useLayoutEffect(()=>{
|
|
13
|
+
ref.current = fn;
|
|
14
|
+
}, [
|
|
15
|
+
fn
|
|
16
|
+
]);
|
|
17
|
+
return useCallback(function() {
|
|
18
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
19
|
+
args[_key] = arguments[_key];
|
|
20
|
+
}
|
|
21
|
+
const f = ref.current;
|
|
22
|
+
return f(...args);
|
|
23
|
+
}, []);
|
|
24
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useContext, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { ReactEditorView } from "../ReactEditorView.js";
|
|
3
3
|
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
|
|
4
4
|
import { EditorContext } from "../contexts/EditorContext.js";
|
|
5
5
|
import { CompositionViewDesc, ReactNodeViewDesc, sortViewDescs } from "../viewdesc.js";
|
|
6
6
|
import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
|
|
7
|
+
import { useEffectEvent } from "./useEffectEvent.js";
|
|
7
8
|
function findContentDOM(source, children) {
|
|
8
9
|
return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
|
|
9
10
|
}
|
|
@@ -15,7 +16,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
15
16
|
const [contentDOM, setContentDOM] = useState(null);
|
|
16
17
|
const viewDescRef = useRef();
|
|
17
18
|
const childrenRef = useRef([]);
|
|
18
|
-
const create =
|
|
19
|
+
const create = useEffectEvent(()=>{
|
|
19
20
|
if (!(view instanceof ReactEditorView)) {
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
@@ -37,13 +38,8 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
37
38
|
setContentDOM(contentDOM);
|
|
38
39
|
setNodeDOM(nodeDOM);
|
|
39
40
|
return viewDesc;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
parentRef,
|
|
43
|
-
constructor,
|
|
44
|
-
view
|
|
45
|
-
]);
|
|
46
|
-
const update = useCallback((props)=>{
|
|
41
|
+
});
|
|
42
|
+
const update = useEffectEvent(()=>{
|
|
47
43
|
if (!(view instanceof ReactEditorView)) {
|
|
48
44
|
return false;
|
|
49
45
|
}
|
|
@@ -64,11 +60,8 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
64
60
|
}
|
|
65
61
|
const { node, decorations, innerDecorations } = props;
|
|
66
62
|
return viewDesc.matchesNode(node, decorations, innerDecorations) || viewDesc.update(node, decorations, innerDecorations, view);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
view
|
|
70
|
-
]);
|
|
71
|
-
const destroy = useCallback(()=>{
|
|
63
|
+
});
|
|
64
|
+
const destroy = useEffectEvent(()=>{
|
|
72
65
|
const viewDesc = viewDescRef.current;
|
|
73
66
|
if (!viewDesc) {
|
|
74
67
|
return;
|
|
@@ -82,13 +75,20 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
82
75
|
setDOM(null);
|
|
83
76
|
setContentDOM(null);
|
|
84
77
|
setNodeDOM(null);
|
|
78
|
+
});
|
|
79
|
+
useClientLayoutEffect(()=>{
|
|
80
|
+
viewDescRef.current = create();
|
|
81
|
+
return ()=>{
|
|
82
|
+
destroy();
|
|
83
|
+
};
|
|
85
84
|
}, [
|
|
86
|
-
|
|
85
|
+
create,
|
|
86
|
+
destroy
|
|
87
87
|
]);
|
|
88
88
|
useClientLayoutEffect(()=>{
|
|
89
|
-
if (!update(
|
|
89
|
+
if (!update()) {
|
|
90
90
|
destroy();
|
|
91
|
-
viewDescRef.current = create(
|
|
91
|
+
viewDescRef.current = create();
|
|
92
92
|
}
|
|
93
93
|
const viewDesc = viewDescRef.current;
|
|
94
94
|
if (!viewDesc) {
|
|
@@ -127,14 +127,6 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
|
-
useClientLayoutEffect(()=>{
|
|
131
|
-
return ()=>{
|
|
132
|
-
destroy();
|
|
133
|
-
viewDescRef.current = undefined;
|
|
134
|
-
};
|
|
135
|
-
}, [
|
|
136
|
-
destroy
|
|
137
|
-
]);
|
|
138
130
|
const childContextValue = useMemo(()=>({
|
|
139
131
|
parentRef: viewDescRef,
|
|
140
132
|
siblingsRef: childrenRef
|