@handlewithcare/react-prosemirror 3.1.0-tiptap.52 → 3.1.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 +3 -0
- package/dist/cjs/ReactEditorView.js +18 -1
- package/dist/cjs/components/ChildNodeViews.js +4 -4
- package/dist/cjs/components/CursorWrapper.js +9 -11
- package/dist/cjs/components/ProseMirror.js +13 -3
- package/dist/cjs/components/TextNodeView.js +54 -50
- package/dist/cjs/components/WidgetView.js +3 -1
- package/dist/cjs/components/nodes/NodeView.js +40 -4
- package/dist/cjs/contexts/CompositionContext.js +14 -0
- package/dist/cjs/decorations/viewDecorations.js +1 -6
- package/dist/cjs/hooks/useEditor.js +2 -10
- package/dist/cjs/hooks/useMarkViewDescription.js +1 -4
- package/dist/cjs/hooks/useNodeViewDescription.js +1 -22
- package/dist/cjs/plugins/beforeInputPlugin.js +162 -50
- package/dist/cjs/plugins/reactKeys.js +34 -15
- package/dist/cjs/tiptap/tiptapNodeView.js +10 -9
- package/dist/cjs/viewdesc.js +55 -4
- package/dist/esm/ReactEditorView.js +18 -1
- package/dist/esm/components/ChildNodeViews.js +5 -5
- package/dist/esm/components/CursorWrapper.js +9 -11
- package/dist/esm/components/ProseMirror.js +13 -3
- package/dist/esm/components/TextNodeView.js +56 -52
- package/dist/esm/components/WidgetView.js +3 -1
- package/dist/esm/components/nodes/NodeView.js +38 -5
- package/dist/esm/contexts/CompositionContext.js +4 -0
- package/dist/esm/decorations/viewDecorations.js +1 -6
- package/dist/esm/hooks/useEditor.js +2 -10
- package/dist/esm/hooks/useIsEditorStatic.js +4 -1
- package/dist/esm/hooks/useMarkViewDescription.js +1 -4
- package/dist/esm/hooks/useNodeViewDescription.js +2 -23
- package/dist/esm/plugins/beforeInputPlugin.js +162 -50
- package/dist/esm/plugins/reactKeys.js +34 -15
- package/dist/esm/tiptap/ReactProseMirrorNodeView.js +1 -1
- package/dist/esm/tiptap/TiptapEditorContent.js +8 -1
- package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +5 -1
- package/dist/esm/tiptap/tiptapNodeView.js +13 -14
- package/dist/esm/viewdesc.js +54 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ReactEditorView.d.ts +10 -1
- package/dist/types/components/ChildNodeViews.d.ts +2 -2
- package/dist/types/components/CursorWrapper.d.ts +1 -1
- package/dist/types/components/TextNodeView.d.ts +7 -4
- package/dist/types/components/__tests__/ProseMirror.composition.test.d.ts +17 -1
- package/dist/types/components/marks/DefaultMarkView.d.ts +1 -1
- package/dist/types/components/marks/MarkView.d.ts +1 -1
- package/dist/types/components/marks/MarkViewConstructorView.d.ts +1 -1
- package/dist/types/components/marks/ReactMarkView.d.ts +1 -1
- package/dist/types/components/nodes/DefaultNodeView.d.ts +1 -1
- package/dist/types/components/nodes/NodeView.d.ts +3 -1
- package/dist/types/components/nodes/NodeViewConstructorView.d.ts +1 -1
- package/dist/types/components/nodes/ReactNodeView.d.ts +1 -1
- package/dist/types/contexts/ChildDescriptionsContext.d.ts +3 -2
- package/dist/types/contexts/CompositionContext.d.ts +4 -0
- package/dist/types/decorations/viewDecorations.d.ts +2 -2
- package/dist/types/hooks/useEditor.d.ts +3 -4
- package/dist/types/hooks/useIsEditorStatic.d.ts +4 -0
- package/dist/types/hooks/useReactKeys.d.ts +2 -5
- package/dist/types/plugins/beforeInputPlugin.d.ts +1 -2
- package/dist/types/plugins/reactKeys.d.ts +10 -9
- package/dist/types/props.d.ts +225 -225
- package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +1 -1
- package/dist/types/tiptap/TiptapEditorContent.d.ts +10 -1
- package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +5 -0
- package/dist/types/tiptap/tiptapNodeView.d.ts +5 -6
- package/dist/types/viewdesc.d.ts +5 -3
- package/package.json +22 -6
- package/dist/cjs/plugins/componentEventListeners.js +0 -28
- package/dist/cjs/plugins/componentEventListenersPlugin.js +0 -35
- package/dist/cjs/tiptap/utils/ssrJSDOMPatch.js +0 -59
- package/dist/esm/plugins/componentEventListeners.js +0 -18
- package/dist/esm/plugins/componentEventListenersPlugin.js +0 -25
- package/dist/esm/tiptap/utils/ssrJSDOMPatch.js +0 -56
- package/dist/types/plugins/componentEventListeners.d.ts +0 -3
- package/dist/types/plugins/componentEventListenersPlugin.d.ts +0 -4
- package/dist/types/tiptap/utils/ssrJSDOMPatch.d.ts +0 -1
package/README.md
CHANGED
|
@@ -99,6 +99,9 @@ import "prosemirror-view/style/prosemirror.css";
|
|
|
99
99
|
|
|
100
100
|
<!-- tocstop -->
|
|
101
101
|
|
|
102
|
+
Already using Tiptap, and interesting in using React ProseMirror as the React
|
|
103
|
+
integration? Check out [the Tiptap integration docs](./src/tiptap/README.md)!
|
|
104
|
+
|
|
102
105
|
## The Problem
|
|
103
106
|
|
|
104
107
|
To make updates efficient, React separates updates into phases so that it can
|
|
@@ -33,6 +33,7 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
33
33
|
nextProps;
|
|
34
34
|
prevState;
|
|
35
35
|
_destroyed;
|
|
36
|
+
cursorWrapped;
|
|
36
37
|
constructor(place, props){
|
|
37
38
|
// Prevent the base class from destroying the React-managed nodes.
|
|
38
39
|
// Restore them below after invoking the base class constructor.
|
|
@@ -85,6 +86,7 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
85
86
|
// @ts-expect-error this violates the typing but class does it, too.
|
|
86
87
|
this.docView = null;
|
|
87
88
|
this._destroyed = false;
|
|
89
|
+
this.cursorWrapped = false;
|
|
88
90
|
}
|
|
89
91
|
get props() {
|
|
90
92
|
return this.nextProps;
|
|
@@ -185,7 +187,22 @@ let ReactEditorView = class ReactEditorView extends _prosemirrorview.EditorView
|
|
|
185
187
|
// this ensures that the base class validates the DOM selection and invokes
|
|
186
188
|
// node view selection callbacks.
|
|
187
189
|
this.docView.markDirty(-1, -1);
|
|
188
|
-
|
|
190
|
+
const selectionChanged = !this.state.selection.eq(this.prevState.selection);
|
|
191
|
+
if (selectionChanged) {
|
|
192
|
+
super.update(this.nextProps);
|
|
193
|
+
} else {
|
|
194
|
+
// If the selection hasn't changed between renders, force prosemirror-view to
|
|
195
|
+
// skip the selectionToDOM call. If a render happens after a DOM selection change
|
|
196
|
+
// but before the "selectionchange" event fired, calling selectionToDOM will cause
|
|
197
|
+
// the selection to be reset its the previous position.
|
|
198
|
+
this.domObserver.setCurSelection();
|
|
199
|
+
this.input.mouseDown = {
|
|
200
|
+
allowDefault: false,
|
|
201
|
+
delayedSelectionSync: false
|
|
202
|
+
};
|
|
203
|
+
super.update(this.nextProps);
|
|
204
|
+
this.input.mouseDown = null;
|
|
205
|
+
}
|
|
189
206
|
// Store the new previous state.
|
|
190
207
|
this.prevState = this.state;
|
|
191
208
|
}
|
|
@@ -118,7 +118,7 @@ const ChildView = /*#__PURE__*/ (0, _react.memo)(function ChildView(param) {
|
|
|
118
118
|
parentRef: parentRef,
|
|
119
119
|
decorations: child.outerDeco
|
|
120
120
|
});
|
|
121
|
-
}) : /*#__PURE__*/ _react.default.createElement(_NodeView.
|
|
121
|
+
}) : /*#__PURE__*/ _react.default.createElement(_NodeView.RemountableNodeView, {
|
|
122
122
|
key: child.key,
|
|
123
123
|
node: child.node,
|
|
124
124
|
getPos: getPos,
|
|
@@ -266,7 +266,7 @@ const ChildElement = /*#__PURE__*/ (0, _react.memo)(function ChildElement(param)
|
|
|
266
266
|
mark: mark,
|
|
267
267
|
getPos: getPos,
|
|
268
268
|
inline: false
|
|
269
|
-
}, element), /*#__PURE__*/ _react.default.createElement(_NodeView.
|
|
269
|
+
}, element), /*#__PURE__*/ _react.default.createElement(_NodeView.RemountableNodeView, {
|
|
270
270
|
key: child.key,
|
|
271
271
|
outerDeco: child.outerDeco,
|
|
272
272
|
node: child.node,
|
|
@@ -399,14 +399,14 @@ const ChildNodeViews = /*#__PURE__*/ (0, _react.memo)(function ChildNodeViews(pa
|
|
|
399
399
|
component: _SeparatorHackView.SeparatorHackView,
|
|
400
400
|
marks: [],
|
|
401
401
|
offset: lastChild?.offset ?? 0,
|
|
402
|
-
index: (lastChild?.index ?? 0) +
|
|
402
|
+
index: (lastChild?.index ?? 0) + 1,
|
|
403
403
|
key: "trailing-hack-img"
|
|
404
404
|
}, {
|
|
405
405
|
type: "hack",
|
|
406
406
|
component: _TrailingHackView.TrailingHackView,
|
|
407
407
|
marks: [],
|
|
408
408
|
offset: lastChild?.offset ?? 0,
|
|
409
|
-
index: (lastChild?.index ?? 0) +
|
|
409
|
+
index: (lastChild?.index ?? 0) + 2,
|
|
410
410
|
key: "trailing-hack-br"
|
|
411
411
|
});
|
|
412
412
|
}
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "CursorWrapper", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
|
+
const _ReactEditorView = require("../ReactEditorView.js");
|
|
12
13
|
const _dom = require("../dom.js");
|
|
13
14
|
const _useEditorEffect = require("../hooks/useEditorEffect.js");
|
|
14
15
|
function _getRequireWildcardCache(nodeInterop) {
|
|
@@ -59,21 +60,18 @@ const CursorWrapper = /*#__PURE__*/ (0, _react.forwardRef)(function CursorWrappe
|
|
|
59
60
|
return innerRef.current;
|
|
60
61
|
}, []);
|
|
61
62
|
(0, _useEditorEffect.useEditorEffect)((view)=>{
|
|
62
|
-
if (!view || !innerRef.current) return;
|
|
63
|
-
// @ts-expect-error Internal property - domObserver
|
|
63
|
+
if (!(view instanceof _ReactEditorView.ReactEditorView) || !innerRef.current) return;
|
|
64
64
|
view.domObserver.disconnectSelection();
|
|
65
|
-
// @ts-expect-error Internal property - domSelection
|
|
66
65
|
const domSel = view.domSelection();
|
|
66
|
+
if (!domSel.isCollapsed) return;
|
|
67
67
|
const node = innerRef.current;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
domSel.collapse(node.parentNode, (0, _dom.domIndex)(node) + 1);
|
|
72
|
-
} else {
|
|
73
|
-
domSel.collapse(node, 0);
|
|
74
|
-
}
|
|
75
|
-
// @ts-expect-error Internal property - domObserver
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
69
|
+
domSel.collapse(node.parentNode, (0, _dom.domIndex)(node) + 1);
|
|
70
|
+
view.cursorWrapped = true;
|
|
76
71
|
view.domObserver.connectSelection();
|
|
72
|
+
return ()=>{
|
|
73
|
+
view.cursorWrapped = false;
|
|
74
|
+
};
|
|
77
75
|
}, []);
|
|
78
76
|
return /*#__PURE__*/ _react.default.createElement("img", {
|
|
79
77
|
ref: innerRef,
|
|
@@ -10,12 +10,14 @@ Object.defineProperty(exports, "ProseMirror", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
12
|
const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
|
|
13
|
+
const _CompositionContext = require("../contexts/CompositionContext.js");
|
|
13
14
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
14
15
|
const _EditorStateContext = require("../contexts/EditorStateContext.js");
|
|
15
16
|
const _NodeViewContext = require("../contexts/NodeViewContext.js");
|
|
16
17
|
const _computeDocDeco = require("../decorations/computeDocDeco.js");
|
|
17
18
|
const _viewDecorations = require("../decorations/viewDecorations.js");
|
|
18
19
|
const _useEditor = require("../hooks/useEditor.js");
|
|
20
|
+
const _reactKeys = require("../plugins/reactKeys.js");
|
|
19
21
|
const _LayoutGroup = require("./LayoutGroup.js");
|
|
20
22
|
const _ProseMirrorDoc = require("./ProseMirrorDoc.js");
|
|
21
23
|
function _getRequireWildcardCache(nodeInterop) {
|
|
@@ -73,7 +75,7 @@ const rootChildDescriptionsContextValue = {
|
|
|
73
75
|
function ProseMirrorInner(param) {
|
|
74
76
|
let { children, nodeViewComponents, markViewComponents, ...props } = param;
|
|
75
77
|
const [mount, setMount] = (0, _react.useState)(null);
|
|
76
|
-
const { editor,
|
|
78
|
+
const { editor, state } = (0, _useEditor.useEditor)(mount, props);
|
|
77
79
|
const nodeViewConstructors = editor.view.nodeViews;
|
|
78
80
|
const nodeViewContextValue = (0, _react.useMemo)(()=>{
|
|
79
81
|
return {
|
|
@@ -90,7 +92,7 @@ function ProseMirrorInner(param) {
|
|
|
90
92
|
]);
|
|
91
93
|
const node = state.doc;
|
|
92
94
|
const decorations = (0, _computeDocDeco.computeDocDeco)(editor.view);
|
|
93
|
-
const innerDecorations = (0, _viewDecorations.viewDecorations)(editor.view
|
|
95
|
+
const innerDecorations = (0, _viewDecorations.viewDecorations)(editor.view);
|
|
94
96
|
const docNodeViewContextValue = (0, _react.useMemo)(()=>({
|
|
95
97
|
setMount,
|
|
96
98
|
node,
|
|
@@ -102,6 +104,12 @@ function ProseMirrorInner(param) {
|
|
|
102
104
|
decorations,
|
|
103
105
|
innerDecorations
|
|
104
106
|
]);
|
|
107
|
+
const freezeFrom = _reactKeys.reactKeysPluginKey.getState(state)?.freezeFrom ?? null;
|
|
108
|
+
const compositionContextValue = (0, _react.useMemo)(()=>({
|
|
109
|
+
freezeFrom
|
|
110
|
+
}), [
|
|
111
|
+
freezeFrom
|
|
112
|
+
]);
|
|
105
113
|
return /*#__PURE__*/ _react.default.createElement(_EditorContext.EditorContext.Provider, {
|
|
106
114
|
value: editor
|
|
107
115
|
}, /*#__PURE__*/ _react.default.createElement(_EditorStateContext.EditorStateContext.Provider, {
|
|
@@ -110,9 +118,11 @@ function ProseMirrorInner(param) {
|
|
|
110
118
|
value: nodeViewContextValue
|
|
111
119
|
}, /*#__PURE__*/ _react.default.createElement(_ChildDescriptionsContext.ChildDescriptionsContext.Provider, {
|
|
112
120
|
value: rootChildDescriptionsContextValue
|
|
121
|
+
}, /*#__PURE__*/ _react.default.createElement(_CompositionContext.CompositionContext.Provider, {
|
|
122
|
+
value: compositionContextValue
|
|
113
123
|
}, /*#__PURE__*/ _react.default.createElement(_ProseMirrorDoc.DocNodeViewContext.Provider, {
|
|
114
124
|
value: docNodeViewContextValue
|
|
115
|
-
}, children)))));
|
|
125
|
+
}, children))))));
|
|
116
126
|
}
|
|
117
127
|
function ProseMirror(props) {
|
|
118
128
|
return /*#__PURE__*/ _react.default.createElement(_LayoutGroup.LayoutGroup, null, /*#__PURE__*/ _react.default.createElement(ProseMirrorInner, props));
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "TextNodeView", {
|
|
|
10
10
|
});
|
|
11
11
|
const _prosemirrorview = require("prosemirror-view");
|
|
12
12
|
const _react = require("react");
|
|
13
|
+
const _ReactEditorView = require("../ReactEditorView.js");
|
|
13
14
|
const _findDOMNode = require("../findDOMNode.js");
|
|
14
15
|
const _viewdesc = require("../viewdesc.js");
|
|
15
16
|
const _ChildNodeViews = require("./ChildNodeViews.js");
|
|
@@ -36,75 +37,78 @@ function shallowEqual(objA, objB) {
|
|
|
36
37
|
return true;
|
|
37
38
|
}
|
|
38
39
|
let TextNodeView = class TextNodeView extends _react.Component {
|
|
39
|
-
viewDescRef =
|
|
40
|
-
|
|
41
|
-
updateEffect() {
|
|
40
|
+
viewDescRef = createMutRef();
|
|
41
|
+
create() {
|
|
42
42
|
const { view, decorations, siblingsRef, parentRef, getPos, node } = this.props;
|
|
43
|
-
// There simply is no other way to ref a text node
|
|
44
|
-
// eslint-disable-next-line react/no-find-dom-node
|
|
45
43
|
const dom = (0, _findDOMNode.findDOMNode)(this);
|
|
46
|
-
|
|
47
|
-
// when a composition was started that produces a new text node.
|
|
48
|
-
// Otherwise we just rely on re-rendering the renderRef
|
|
49
|
-
if (!dom) {
|
|
50
|
-
if (!view.composing) return;
|
|
51
|
-
this.viewDescRef = new _viewdesc.CompositionViewDesc(parentRef.current, getPos, // These are just placeholders/dummies. We can't
|
|
52
|
-
// actually find the correct DOM nodes from here,
|
|
53
|
-
// so we let our parent do it.
|
|
54
|
-
// Passing a valid element here just so that the
|
|
55
|
-
// ViewDesc constructor doesn't blow up.
|
|
56
|
-
document.createElement("div"), document.createTextNode(node.text ?? ""), node.text ?? "");
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
44
|
+
if (!dom && !view.composing) return null;
|
|
59
45
|
let textNode = dom;
|
|
60
|
-
while(textNode
|
|
46
|
+
while(textNode?.firstChild){
|
|
61
47
|
textNode = textNode.firstChild;
|
|
62
48
|
}
|
|
63
|
-
if (!
|
|
64
|
-
|
|
65
|
-
} else {
|
|
66
|
-
this.viewDescRef.parent = parentRef.current;
|
|
67
|
-
this.viewDescRef.children = [];
|
|
68
|
-
this.viewDescRef.node = node;
|
|
69
|
-
this.viewDescRef.outerDeco = decorations;
|
|
70
|
-
this.viewDescRef.innerDeco = _prosemirrorview.DecorationSet.empty;
|
|
71
|
-
this.viewDescRef.dom = dom;
|
|
72
|
-
this.viewDescRef.dom.pmViewDesc = this.viewDescRef;
|
|
73
|
-
this.viewDescRef.nodeDOM = textNode;
|
|
74
|
-
}
|
|
75
|
-
if (!siblingsRef.current.includes(this.viewDescRef)) {
|
|
76
|
-
siblingsRef.current.push(this.viewDescRef);
|
|
49
|
+
if (!(textNode instanceof Text)) {
|
|
50
|
+
textNode = null;
|
|
77
51
|
}
|
|
52
|
+
if (!dom || !textNode) return null;
|
|
53
|
+
const viewDesc = new _viewdesc.TextViewDesc(parentRef.current, [], getPos, node, decorations, _prosemirrorview.DecorationSet.empty, dom, textNode);
|
|
54
|
+
siblingsRef.current.push(viewDesc);
|
|
78
55
|
siblingsRef.current.sort(_viewdesc.sortViewDescs);
|
|
56
|
+
return viewDesc;
|
|
57
|
+
}
|
|
58
|
+
update() {
|
|
59
|
+
const { view, node, decorations } = this.props;
|
|
60
|
+
if (!(view instanceof _ReactEditorView.ReactEditorView)) return false;
|
|
61
|
+
const viewDesc = this.viewDescRef.current;
|
|
62
|
+
if (!viewDesc) return false;
|
|
63
|
+
const dom = (0, _findDOMNode.findDOMNode)(this);
|
|
64
|
+
if (!dom || dom !== viewDesc.dom) return false;
|
|
65
|
+
if (!dom.contains(viewDesc.nodeDOM)) return false;
|
|
66
|
+
return viewDesc.matchesNode(node, decorations, _prosemirrorview.DecorationSet.empty) || viewDesc.update(node, decorations, _prosemirrorview.DecorationSet.empty, view);
|
|
67
|
+
}
|
|
68
|
+
destroy() {
|
|
69
|
+
const viewDesc = this.viewDescRef.current;
|
|
70
|
+
if (!viewDesc) return;
|
|
71
|
+
viewDesc.destroy();
|
|
72
|
+
const siblings = this.props.siblingsRef.current;
|
|
73
|
+
if (siblings.includes(viewDesc)) {
|
|
74
|
+
const index = siblings.indexOf(viewDesc);
|
|
75
|
+
siblings.splice(index, 1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
updateEffect() {
|
|
79
|
+
if (!this.update()) {
|
|
80
|
+
this.destroy();
|
|
81
|
+
this.viewDescRef.current = this.create();
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
shouldComponentUpdate(nextProps) {
|
|
81
85
|
return !shallowEqual(this.props, nextProps);
|
|
82
86
|
}
|
|
87
|
+
constructor(props){
|
|
88
|
+
super(props);
|
|
89
|
+
this.viewDescRef.current = null;
|
|
90
|
+
}
|
|
83
91
|
componentDidMount() {
|
|
92
|
+
this.viewDescRef.current = this.create();
|
|
84
93
|
this.updateEffect();
|
|
85
94
|
}
|
|
86
95
|
componentDidUpdate() {
|
|
87
96
|
this.updateEffect();
|
|
97
|
+
const { view } = this.props;
|
|
98
|
+
if (!(view instanceof _ReactEditorView.ReactEditorView)) return;
|
|
88
99
|
}
|
|
89
100
|
componentWillUnmount() {
|
|
90
|
-
|
|
91
|
-
if (!this.viewDescRef) return;
|
|
92
|
-
if (siblingsRef.current.includes(this.viewDescRef)) {
|
|
93
|
-
const index = siblingsRef.current.indexOf(this.viewDescRef);
|
|
94
|
-
siblingsRef.current.splice(index, 1);
|
|
95
|
-
}
|
|
101
|
+
this.destroy();
|
|
96
102
|
}
|
|
97
103
|
render() {
|
|
98
|
-
const {
|
|
99
|
-
|
|
100
|
-
// update the DOM that the user is working in. If there's
|
|
101
|
-
// an active composition and the selection is in this node,
|
|
102
|
-
// we freeze the DOM of this element so that it doesn't
|
|
103
|
-
// interrupt the composition
|
|
104
|
-
if (view.composing && view.state.selection.from >= getPos() && view.state.selection.from <= getPos() + node.nodeSize) {
|
|
105
|
-
return this.renderRef;
|
|
106
|
-
}
|
|
107
|
-
this.renderRef = decorations.reduce(_ChildNodeViews.wrapInDeco, node.text);
|
|
108
|
-
return this.renderRef;
|
|
104
|
+
const { node, decorations } = this.props;
|
|
105
|
+
return decorations.reduce(_ChildNodeViews.wrapInDeco, node.text);
|
|
109
106
|
}
|
|
110
107
|
};
|
|
108
|
+
/**
|
|
109
|
+
* createRef returns a RefObject, even though the docs
|
|
110
|
+
* say that it's acceptible to manage the ref's value
|
|
111
|
+
* yourself.
|
|
112
|
+
*/ function createMutRef() {
|
|
113
|
+
return /*#__PURE__*/ (0, _react.createRef)();
|
|
114
|
+
}
|
|
@@ -14,9 +14,13 @@ _export(exports, {
|
|
|
14
14
|
},
|
|
15
15
|
NodeView: function() {
|
|
16
16
|
return NodeView;
|
|
17
|
+
},
|
|
18
|
+
RemountableNodeView: function() {
|
|
19
|
+
return RemountableNodeView;
|
|
17
20
|
}
|
|
18
21
|
});
|
|
19
22
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
23
|
+
const _CompositionContext = require("../../contexts/CompositionContext.js");
|
|
20
24
|
const _NodeViewContext = require("../../contexts/NodeViewContext.js");
|
|
21
25
|
const _DefaultNodeView = require("./DefaultNodeView.js");
|
|
22
26
|
const _NodeViewConstructorView = require("./NodeViewConstructorView.js");
|
|
@@ -62,8 +66,12 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
62
66
|
}
|
|
63
67
|
return newObj;
|
|
64
68
|
}
|
|
65
|
-
const NodeView = /*#__PURE__*/ (0, _react.memo)(function NodeView(
|
|
69
|
+
const NodeView = /*#__PURE__*/ (0, _react.memo)(function NodeView(param) {
|
|
70
|
+
let { forceRemount, ...props } = param;
|
|
71
|
+
const renderRef = (0, _react.useRef)(null);
|
|
72
|
+
const { freezeFrom } = (0, _react.useContext)(_CompositionContext.CompositionContext);
|
|
66
73
|
const { components, constructors } = (0, _react.useContext)(_NodeViewContext.NodeViewContext);
|
|
74
|
+
const committedFrozenRef = (0, _react.useRef)(false);
|
|
67
75
|
const component = components[props.node.type.name] ?? _DefaultNodeView.DefaultNodeView;
|
|
68
76
|
const constructor = constructors[props.node.type.name];
|
|
69
77
|
// Construct a wrapper component so that the node view remounts when either
|
|
@@ -90,8 +98,36 @@ const NodeView = /*#__PURE__*/ (0, _react.memo)(function NodeView(props) {
|
|
|
90
98
|
constructor,
|
|
91
99
|
component
|
|
92
100
|
]);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
// It's not generally safe to access getPos during render, because the
|
|
102
|
+
// component may not re-render when its return value would change. Here it's
|
|
103
|
+
// safe because we only use it to _suppress_ commits that would otherwise
|
|
104
|
+
// have happened.
|
|
105
|
+
const frozen = props.getPos() === freezeFrom;
|
|
106
|
+
// Protect content while frozen, and also through the single render where we
|
|
107
|
+
// leave the frozen state: `committedFrozenRef` still reflects the previous
|
|
108
|
+
// commit, so we keep returning the exact same cached element reference.
|
|
109
|
+
const protecting = (frozen || committedFrozenRef.current) && renderRef.current != null;
|
|
110
|
+
if (!protecting) {
|
|
111
|
+
renderRef.current = /*#__PURE__*/ _react.default.createElement(GetPosContext.Provider, {
|
|
112
|
+
value: props.getPos
|
|
113
|
+
}, /*#__PURE__*/ _react.default.createElement(Component, props));
|
|
114
|
+
}
|
|
115
|
+
(0, _react.useLayoutEffect)(()=>{
|
|
116
|
+
const wasFrozen = committedFrozenRef.current;
|
|
117
|
+
committedFrozenRef.current = frozen;
|
|
118
|
+
if (wasFrozen && !frozen) forceRemount();
|
|
119
|
+
}, [
|
|
120
|
+
frozen,
|
|
121
|
+
forceRemount
|
|
122
|
+
]);
|
|
123
|
+
return renderRef.current;
|
|
96
124
|
});
|
|
97
125
|
const GetPosContext = /*#__PURE__*/ (0, _react.createContext)(null);
|
|
126
|
+
function RemountableNodeView(props) {
|
|
127
|
+
const [key, forceRemount] = (0, _react.useReducer)((x)=>x + 1, 0);
|
|
128
|
+
return /*#__PURE__*/ _react.default.createElement(NodeView, {
|
|
129
|
+
key: key.toString(),
|
|
130
|
+
...props,
|
|
131
|
+
forceRemount: forceRemount
|
|
132
|
+
});
|
|
133
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "CompositionContext", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return CompositionContext;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = require("react");
|
|
12
|
+
const CompositionContext = (0, _react.createContext)({
|
|
13
|
+
freezeFrom: null
|
|
14
|
+
});
|
|
@@ -123,17 +123,12 @@ function insertAhead(array, i, deco) {
|
|
|
123
123
|
array.splice(i, 0, deco);
|
|
124
124
|
}
|
|
125
125
|
const ViewDecorationsCache = new WeakMap();
|
|
126
|
-
function viewDecorations(view
|
|
126
|
+
function viewDecorations(view) {
|
|
127
127
|
const found = [];
|
|
128
128
|
view.someProp("decorations", (f)=>{
|
|
129
129
|
const result = f(view.state);
|
|
130
130
|
if (result && result != empty) found.push(result);
|
|
131
131
|
});
|
|
132
|
-
if (cursorWrapper) {
|
|
133
|
-
found.push(_prosemirrorview.DecorationSet.create(view.state.doc, [
|
|
134
|
-
cursorWrapper
|
|
135
|
-
]));
|
|
136
|
-
}
|
|
137
132
|
const previous = ViewDecorationsCache.get(view);
|
|
138
133
|
if (!previous) {
|
|
139
134
|
const result = DecorationGroup.from(found);
|
|
@@ -27,23 +27,16 @@ function useEditor(mount, options) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
const flushSyncRef = (0, _react.useRef)(true);
|
|
30
|
-
const [cursorWrapper, _setCursorWrapper] = (0, _react.useState)(null);
|
|
31
30
|
const forceUpdate = (0, _useForceUpdate.useForceUpdate)();
|
|
32
31
|
const defaultState = options.defaultState ?? _constants.EMPTY_STATE;
|
|
33
32
|
const [_state, setState] = (0, _react.useState)(defaultState);
|
|
34
33
|
const state = options.state ?? _state;
|
|
35
34
|
const { handleDOMEvents, registerEventListener, unregisterEventListener } = (0, _useComponentEventListeners.useComponentEventListeners)(options.handleDOMEvents);
|
|
36
|
-
const setCursorWrapper = (0, _react.useCallback)((deco)=>{
|
|
37
|
-
(0, _reactdom.flushSync)(()=>{
|
|
38
|
-
_setCursorWrapper(deco);
|
|
39
|
-
});
|
|
40
|
-
}, []);
|
|
41
35
|
const plugins = (0, _react.useMemo)(()=>[
|
|
42
36
|
...options.plugins ?? [],
|
|
43
|
-
(0, _beforeInputPlugin.beforeInputPlugin)(
|
|
37
|
+
(0, _beforeInputPlugin.beforeInputPlugin)()
|
|
44
38
|
], [
|
|
45
|
-
options.plugins
|
|
46
|
-
setCursorWrapper
|
|
39
|
+
options.plugins
|
|
47
40
|
]);
|
|
48
41
|
const dispatchTransaction = (0, _react.useCallback)(function dispatchTransaction(tr) {
|
|
49
42
|
if (flushSyncRef.current) {
|
|
@@ -122,7 +115,6 @@ function useEditor(mount, options) {
|
|
|
122
115
|
]);
|
|
123
116
|
return {
|
|
124
117
|
editor,
|
|
125
|
-
cursorWrapper,
|
|
126
118
|
state
|
|
127
119
|
};
|
|
128
120
|
}
|
|
@@ -123,10 +123,7 @@ function useMarkViewDescription(getDOM, getContentDOM, constructor, props) {
|
|
|
123
123
|
const childContextValue = (0, _react.useMemo)(()=>({
|
|
124
124
|
parentRef: viewDescRef,
|
|
125
125
|
siblingsRef: childrenRef
|
|
126
|
-
}), [
|
|
127
|
-
childrenRef,
|
|
128
|
-
viewDescRef
|
|
129
|
-
]);
|
|
126
|
+
}), []);
|
|
130
127
|
return {
|
|
131
128
|
childContextValue,
|
|
132
129
|
contentDOM: contentDOMRef.current ?? viewDescRef.current?.dom,
|
|
@@ -141,33 +141,12 @@ function useNodeViewDescription(getDOM, getContentDOM, constructor, props) {
|
|
|
141
141
|
children.sort(_viewdesc.sortViewDescs);
|
|
142
142
|
for (const child of children){
|
|
143
143
|
child.parent = viewDesc;
|
|
144
|
-
// Because TextNodeViews can't locate the DOM nodes
|
|
145
|
-
// for compositions, we need to override them here
|
|
146
|
-
if (child instanceof _viewdesc.CompositionViewDesc) {
|
|
147
|
-
const compositionTopDOM = viewDesc?.contentDOM?.firstChild;
|
|
148
|
-
if (!compositionTopDOM) throw new Error(`Started a composition but couldn't find the text node it belongs to.`);
|
|
149
|
-
let textDOM = compositionTopDOM;
|
|
150
|
-
while(textDOM.firstChild){
|
|
151
|
-
textDOM = textDOM.firstChild;
|
|
152
|
-
}
|
|
153
|
-
if (!textDOM || !(textDOM instanceof Text)) throw new Error(`Started a composition but couldn't find the text node it belongs to.`);
|
|
154
|
-
child.dom = compositionTopDOM;
|
|
155
|
-
child.textDOM = textDOM;
|
|
156
|
-
child.text = textDOM.data;
|
|
157
|
-
child.textDOM.pmViewDesc = child;
|
|
158
|
-
// It should not be possible to be in a composition because one could
|
|
159
|
-
// not start between the renders that switch the view type.
|
|
160
|
-
view.input.compositionNodes.push(child);
|
|
161
|
-
}
|
|
162
144
|
}
|
|
163
145
|
});
|
|
164
146
|
const childContextValue = (0, _react.useMemo)(()=>({
|
|
165
147
|
parentRef: viewDescRef,
|
|
166
148
|
siblingsRef: childrenRef
|
|
167
|
-
}), [
|
|
168
|
-
childrenRef,
|
|
169
|
-
viewDescRef
|
|
170
|
-
]);
|
|
149
|
+
}), []);
|
|
171
150
|
return {
|
|
172
151
|
childContextValue,
|
|
173
152
|
contentDOM: contentDOMRef.current,
|