@handlewithcare/react-prosemirror 2.5.0 → 2.5.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/dist/cjs/ReactEditorView.js +6 -6
- package/dist/cjs/components/ChildNodeViews.js +6 -6
- package/dist/cjs/components/CustomNodeView.js +77 -121
- package/dist/cjs/components/DefaultNodeView.js +67 -0
- package/dist/cjs/components/DocNodeView.js +33 -32
- package/dist/cjs/components/NodeView.js +31 -21
- package/dist/cjs/components/ProseMirror.js +20 -9
- package/dist/cjs/components/ProseMirrorDoc.js +7 -27
- package/dist/cjs/components/ReactNodeView.js +96 -58
- package/dist/cjs/hooks/useEditor.js +1 -1
- package/dist/cjs/hooks/useIgnoreMutation.js +1 -1
- package/dist/cjs/hooks/useNodeViewDescriptor.js +121 -78
- package/dist/cjs/hooks/useSelectNode.js +9 -7
- package/dist/cjs/hooks/useStopEvent.js +1 -1
- package/dist/cjs/plugins/beforeInputPlugin.js +12 -0
- package/dist/cjs/viewdesc.js +95 -17
- package/dist/esm/ReactEditorView.js +6 -6
- package/dist/esm/components/ChildNodeViews.js +6 -6
- package/dist/esm/components/CustomNodeView.js +78 -122
- package/dist/esm/components/DefaultNodeView.js +16 -0
- package/dist/esm/components/DocNodeView.js +33 -32
- package/dist/esm/components/NodeView.js +32 -22
- package/dist/esm/components/ProseMirror.js +20 -9
- package/dist/esm/components/ProseMirrorDoc.js +7 -28
- package/dist/esm/components/ReactNodeView.js +97 -59
- package/dist/esm/hooks/useEditor.js +1 -1
- package/dist/esm/hooks/useIgnoreMutation.js +1 -1
- package/dist/esm/hooks/useNodeViewDescriptor.js +123 -80
- package/dist/esm/hooks/useSelectNode.js +9 -7
- package/dist/esm/hooks/useStopEvent.js +1 -1
- package/dist/esm/plugins/beforeInputPlugin.js +12 -0
- package/dist/esm/viewdesc.js +92 -17
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/ReactEditorView.d.ts +3 -2
- package/dist/types/components/CustomNodeView.d.ts +1 -1
- package/dist/types/components/DefaultNodeView.d.ts +3 -0
- package/dist/types/components/DocNodeView.d.ts +8 -13
- package/dist/types/components/NodeView.d.ts +4 -4
- package/dist/types/components/NodeViewComponentProps.d.ts +3 -4
- package/dist/types/components/ProseMirrorDoc.d.ts +14 -8
- package/dist/types/components/ReactNodeView.d.ts +3 -1
- package/dist/types/contexts/IgnoreMutationContext.d.ts +2 -1
- package/dist/types/contexts/NodeViewContext.d.ts +3 -1
- package/dist/types/contexts/SelectNodeContext.d.ts +3 -1
- package/dist/types/contexts/StopEventContext.d.ts +2 -1
- package/dist/types/hooks/useEditor.d.ts +1 -1
- package/dist/types/hooks/useNodeViewDescriptor.d.ts +18 -10
- package/dist/types/hooks/useSelectNode.d.ts +2 -1
- package/dist/types/viewdesc.d.ts +25 -8
- package/package.json +3 -3
- package/dist/cjs/hooks/useClientOnly.js +0 -19
- package/dist/esm/hooks/useClientOnly.js +0 -9
- package/dist/types/hooks/useClientOnly.d.ts +0 -1
|
@@ -33,9 +33,6 @@ function changedNodeViews(a, b) {
|
|
|
33
33
|
nextProps;
|
|
34
34
|
prevState;
|
|
35
35
|
constructor(place, props){
|
|
36
|
-
// By the time the editor view mounts this should exist.
|
|
37
|
-
// We assume it is not possible to set the mount point otherwise.
|
|
38
|
-
const docView = place.mount.pmViewDesc;
|
|
39
36
|
// Prevent the base class from destroying the React-managed nodes.
|
|
40
37
|
// Restore them below after invoking the base class constructor.
|
|
41
38
|
const reactContent = [
|
|
@@ -71,8 +68,11 @@ function changedNodeViews(a, b) {
|
|
|
71
68
|
this.nextProps = props;
|
|
72
69
|
this.state = props.state;
|
|
73
70
|
this.nodeViews = buildNodeViews(this);
|
|
74
|
-
|
|
75
|
-
this
|
|
71
|
+
// Destroy the document view description that the base class makes.
|
|
72
|
+
// A React document view will assign itself to this attribute later.
|
|
73
|
+
this.docView.destroy();
|
|
74
|
+
// @ts-expect-error this violates the typing but class does it, too.
|
|
75
|
+
this.docView = null;
|
|
76
76
|
}
|
|
77
77
|
get props() {
|
|
78
78
|
return this.nextProps;
|
|
@@ -87,7 +87,7 @@ function changedNodeViews(a, b) {
|
|
|
87
87
|
const prevProps = this.nextProps;
|
|
88
88
|
this.nextProps = props;
|
|
89
89
|
this.state = props.state;
|
|
90
|
-
if (prevProps.state.plugins !== props.state.plugins || prevProps.plugins !== props.plugins) {
|
|
90
|
+
if (prevProps.state.plugins !== props.state.plugins || prevProps.plugins !== props.plugins || prevProps.nodeViews !== props.nodeViews) {
|
|
91
91
|
const nodeViews = buildNodeViews(this);
|
|
92
92
|
if (changedNodeViews(this.nodeViews, nodeViews)) {
|
|
93
93
|
this.nodeViews = nodeViews;
|
|
@@ -333,18 +333,18 @@ export const ChildNodeViews = /*#__PURE__*/ memo(function ChildNodeViews(param)
|
|
|
333
333
|
/\n$/.test(lastChild.node.text)) {
|
|
334
334
|
children.push({
|
|
335
335
|
type: "hack",
|
|
336
|
-
component:
|
|
336
|
+
component: SeparatorHackView,
|
|
337
337
|
marks: [],
|
|
338
338
|
offset: lastChild?.offset ?? 0,
|
|
339
|
-
index: (lastChild?.index ?? 0) +
|
|
340
|
-
key: "trailing-hack-
|
|
339
|
+
index: (lastChild?.index ?? 0) + 2,
|
|
340
|
+
key: "trailing-hack-img"
|
|
341
341
|
}, {
|
|
342
342
|
type: "hack",
|
|
343
|
-
component:
|
|
343
|
+
component: TrailingHackView,
|
|
344
344
|
marks: [],
|
|
345
345
|
offset: lastChild?.offset ?? 0,
|
|
346
|
-
index: (lastChild?.index ?? 0) +
|
|
347
|
-
key: "trailing-hack-
|
|
346
|
+
index: (lastChild?.index ?? 0) + 1,
|
|
347
|
+
key: "trailing-hack-br"
|
|
348
348
|
});
|
|
349
349
|
}
|
|
350
350
|
}
|
|
@@ -1,137 +1,93 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DOMSerializer } from "prosemirror-model";
|
|
2
|
+
import React, { cloneElement, createElement, memo, useMemo, useRef, useState } from "react";
|
|
2
3
|
import { createPortal } from "react-dom";
|
|
3
4
|
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
|
|
4
|
-
import { EditorContext } from "../contexts/EditorContext.js";
|
|
5
|
-
import { useClientLayoutEffect } from "../hooks/useClientLayoutEffect.js";
|
|
6
|
-
import { useClientOnly } from "../hooks/useClientOnly.js";
|
|
7
|
-
import { useForceUpdate } from "../hooks/useForceUpdate.js";
|
|
8
5
|
import { useNodeViewDescriptor } from "../hooks/useNodeViewDescriptor.js";
|
|
9
6
|
import { ChildNodeViews, wrapInDeco } from "./ChildNodeViews.js";
|
|
10
7
|
export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param) {
|
|
11
|
-
let {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
outerDecoRef.current = outerDeco;
|
|
22
|
-
const innerDecoRef = useRef(innerDeco);
|
|
23
|
-
innerDecoRef.current = innerDeco;
|
|
24
|
-
const customNodeViewRootRef = useRef(null);
|
|
25
|
-
const customNodeViewRef = useRef(null);
|
|
26
|
-
const forceUpdate = useForceUpdate();
|
|
27
|
-
const isOnClient = useClientOnly();
|
|
28
|
-
// In Strict/Concurrent mode, layout effects can be destroyed/re-run
|
|
29
|
-
// independently of renders. We need to ensure that if the
|
|
30
|
-
// destructor that destroys the node view is called, we then recreate
|
|
31
|
-
// the node view when the layout effect is re-run.
|
|
32
|
-
useClientLayoutEffect(()=>{
|
|
33
|
-
if (!customNodeViewRef.current) {
|
|
34
|
-
customNodeViewRef.current = customNodeView(nodeRef.current, view, getPos, outerDecoRef.current, innerDecoRef.current);
|
|
35
|
-
if (customNodeViewRef.current.stopEvent) {
|
|
36
|
-
setStopEvent(customNodeViewRef.current.stopEvent.bind(customNodeViewRef.current));
|
|
37
|
-
}
|
|
38
|
-
if (customNodeViewRef.current.selectNode) {
|
|
39
|
-
setSelectNode(customNodeViewRef.current.selectNode.bind(customNodeViewRef.current), customNodeViewRef.current.deselectNode?.bind(customNodeViewRef.current) ?? (()=>{}));
|
|
40
|
-
}
|
|
41
|
-
if (customNodeViewRef.current.ignoreMutation) {
|
|
42
|
-
setIgnoreMutation(customNodeViewRef.current.ignoreMutation.bind(customNodeViewRef.current));
|
|
43
|
-
}
|
|
44
|
-
// If we've reconstructed the nodeview, then we need to
|
|
45
|
-
// recreate the portal into its contentDOM, which happens
|
|
46
|
-
// during the render. So we need to trigger a re-render!
|
|
47
|
-
forceUpdate();
|
|
48
|
-
}
|
|
49
|
-
if (!customNodeViewRootRef.current) return;
|
|
50
|
-
const { dom } = customNodeViewRef.current;
|
|
51
|
-
if (customNodeViewRootRef.current.firstChild === dom) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
nodeDomRef.current = customNodeViewRootRef.current;
|
|
55
|
-
customNodeViewRootRef.current.appendChild(dom);
|
|
56
|
-
const nodeView = customNodeViewRef.current;
|
|
57
|
-
return ()=>{
|
|
58
|
-
nodeView.destroy?.();
|
|
59
|
-
customNodeViewRef.current = null;
|
|
60
|
-
};
|
|
61
|
-
// setStopEvent, setSelectNodee, and setIgnoreMutation are all stable
|
|
62
|
-
// functions and don't need to be added to the dependencies. They also
|
|
63
|
-
// can't be, because they come from useNodeViewDescriptor, which
|
|
64
|
-
// _has_ to be called after this hook, so that the effects run
|
|
65
|
-
// in the correct order
|
|
66
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
-
}, [
|
|
68
|
-
customNodeView,
|
|
69
|
-
getPos,
|
|
70
|
-
view
|
|
71
|
-
]);
|
|
72
|
-
useClientLayoutEffect(()=>{
|
|
73
|
-
if (!customNodeView || !customNodeViewRef.current) return;
|
|
74
|
-
const { destroy, update } = customNodeViewRef.current;
|
|
75
|
-
const updated = update?.call(customNodeViewRef.current, node, outerDeco, innerDeco) ?? true;
|
|
76
|
-
if (updated) return;
|
|
77
|
-
destroy?.call(customNodeViewRef.current);
|
|
78
|
-
if (!customNodeViewRootRef.current) return;
|
|
79
|
-
customNodeViewRef.current = customNodeView(nodeRef.current, view, getPos, outerDecoRef.current, innerDecoRef.current);
|
|
80
|
-
const { dom } = customNodeViewRef.current;
|
|
81
|
-
nodeDomRef.current = customNodeViewRootRef.current;
|
|
82
|
-
customNodeViewRootRef.current.appendChild(dom);
|
|
83
|
-
}, [
|
|
84
|
-
customNodeView,
|
|
85
|
-
view,
|
|
86
|
-
innerDeco,
|
|
8
|
+
let { constructor, node, getPos, innerDeco, outerDeco } = param;
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
const innerRef = useRef(null);
|
|
11
|
+
const [selected, setSelected] = useState(false);
|
|
12
|
+
const nodeProps = useMemo(()=>({
|
|
13
|
+
node,
|
|
14
|
+
getPos,
|
|
15
|
+
decorations: outerDeco,
|
|
16
|
+
innerDecorations: innerDeco
|
|
17
|
+
}), [
|
|
87
18
|
node,
|
|
19
|
+
getPos,
|
|
88
20
|
outerDeco,
|
|
89
|
-
|
|
90
|
-
]);
|
|
91
|
-
const { childDescriptors, nodeViewDescRef, setStopEvent, setSelectNode, setIgnoreMutation } = useNodeViewDescriptor(node, getPos, domRef, nodeDomRef, innerDeco, outerDeco, contentDomRef);
|
|
92
|
-
const childContextValue = useMemo(()=>({
|
|
93
|
-
parentRef: nodeViewDescRef,
|
|
94
|
-
siblingsRef: childDescriptors
|
|
95
|
-
}), [
|
|
96
|
-
childDescriptors,
|
|
97
|
-
nodeViewDescRef
|
|
21
|
+
innerDeco
|
|
98
22
|
]);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// render function here. We only do this once, and the
|
|
103
|
-
// results are stored in a ref but not actually appended
|
|
104
|
-
// to the DOM until a client effect
|
|
105
|
-
if (!customNodeViewRef.current) {
|
|
106
|
-
customNodeViewRef.current = customNodeView(nodeRef.current, view, getPos, outerDecoRef.current, innerDecoRef.current);
|
|
107
|
-
if (customNodeViewRef.current.stopEvent) {
|
|
108
|
-
setStopEvent(customNodeViewRef.current.stopEvent.bind(customNodeViewRef.current));
|
|
23
|
+
const createNodeView = function() {
|
|
24
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
25
|
+
args[_key] = arguments[_key];
|
|
109
26
|
}
|
|
110
|
-
|
|
111
|
-
|
|
27
|
+
const nodeView = constructor(...args);
|
|
28
|
+
if (!nodeView || !nodeView.dom) {
|
|
29
|
+
const spec = node.type.spec.toDOM?.(node);
|
|
30
|
+
if (!spec) {
|
|
31
|
+
throw new Error(`Node spec for ${node.type.name} is missing toDOM`);
|
|
32
|
+
}
|
|
33
|
+
return DOMSerializer.renderSpec(document, spec, null);
|
|
112
34
|
}
|
|
113
|
-
|
|
114
|
-
|
|
35
|
+
return nodeView;
|
|
36
|
+
};
|
|
37
|
+
const { childContextValue, contentDOM } = useNodeViewDescriptor(ref, function() {
|
|
38
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
39
|
+
args[_key] = arguments[_key];
|
|
115
40
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
ref
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
41
|
+
setSelected(false);
|
|
42
|
+
const nodeView = createNodeView(...args);
|
|
43
|
+
const contentDOM = nodeView.contentDOM;
|
|
44
|
+
const nodeDOM = nodeView.dom;
|
|
45
|
+
const wrapperDOM = innerRef.current ?? ref.current;
|
|
46
|
+
wrapperDOM.appendChild(nodeDOM);
|
|
47
|
+
if (!contentDOM && nodeDOM instanceof HTMLElement && nodeDOM.tagName !== "BR") {
|
|
48
|
+
if (!nodeDOM.hasAttribute("contenteditable")) {
|
|
49
|
+
nodeDOM.contentEditable = "false";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
...nodeView,
|
|
54
|
+
destroy () {
|
|
55
|
+
if (nodeView.destroy) {
|
|
56
|
+
nodeView.destroy();
|
|
57
|
+
}
|
|
58
|
+
wrapperDOM.removeChild(nodeDOM);
|
|
59
|
+
},
|
|
60
|
+
selectNode: nodeView.selectNode?.bind(nodeView) ?? (()=>{
|
|
61
|
+
if (nodeDOM instanceof HTMLElement) {
|
|
62
|
+
nodeDOM.classList.add("ProseMirror-selectednode");
|
|
63
|
+
}
|
|
64
|
+
setSelected(true);
|
|
65
|
+
}),
|
|
66
|
+
deselectNode: nodeView.deselectNode?.bind(nodeView) ?? (()=>{
|
|
67
|
+
if (nodeDOM instanceof HTMLElement) {
|
|
68
|
+
nodeDOM.classList.remove("ProseMirror-selectednode");
|
|
69
|
+
}
|
|
70
|
+
setSelected(false);
|
|
71
|
+
}),
|
|
72
|
+
stopEvent: nodeView.stopEvent?.bind(nodeView),
|
|
73
|
+
ignoreMutation: nodeView.ignoreMutation?.bind(nodeView)
|
|
74
|
+
};
|
|
75
|
+
}, nodeProps);
|
|
76
|
+
const children = !node.isLeaf && contentDOM ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
|
|
77
|
+
value: childContextValue
|
|
78
|
+
}, /*#__PURE__*/ React.createElement(ChildNodeViews, {
|
|
124
79
|
getPos: getPos,
|
|
125
80
|
node: node,
|
|
126
81
|
innerDecorations: innerDeco
|
|
127
|
-
}), contentDOM)
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
82
|
+
})), contentDOM) : null;
|
|
83
|
+
const innerElement = /*#__PURE__*/ createElement(node.isInline ? "span" : "div", {
|
|
84
|
+
ref: innerRef
|
|
85
|
+
}, children);
|
|
86
|
+
const props = {
|
|
87
|
+
...selected || node.type.spec.draggable ? {
|
|
88
|
+
draggable: true
|
|
89
|
+
} : null,
|
|
90
|
+
ref
|
|
91
|
+
};
|
|
92
|
+
return /*#__PURE__*/ cloneElement(outerDeco.reduce(wrapInDeco, innerElement), props);
|
|
137
93
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo } from "react";
|
|
2
|
+
import { OutputSpec } from "./OutputSpec.js";
|
|
3
|
+
export const DefaultNodeView = /*#__PURE__*/ forwardRef(function DefaultNodeView(param, ref) {
|
|
4
|
+
let { nodeProps: { node }, children, ...props } = param;
|
|
5
|
+
const spec = useMemo(()=>node.type.spec.toDOM?.(node), [
|
|
6
|
+
node
|
|
7
|
+
]);
|
|
8
|
+
if (!spec) {
|
|
9
|
+
throw new Error(`Node spec for ${node.type.name} is missing toDOM`);
|
|
10
|
+
}
|
|
11
|
+
return /*#__PURE__*/ React.createElement(OutputSpec, {
|
|
12
|
+
...props,
|
|
13
|
+
outputSpec: spec,
|
|
14
|
+
ref: ref
|
|
15
|
+
}, children);
|
|
16
|
+
});
|
|
@@ -1,44 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
// this linting rule is only broken in this file
|
|
3
|
-
/* eslint-disable react/prop-types */ import React, { cloneElement, createElement, forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
|
|
1
|
+
import React, { cloneElement, createElement, forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
|
|
4
2
|
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
|
|
5
3
|
import { useNodeViewDescriptor } from "../hooks/useNodeViewDescriptor.js";
|
|
6
4
|
import { ChildNodeViews, wrapInDeco } from "./ChildNodeViews.js";
|
|
7
|
-
function getPos() {
|
|
8
|
-
return -1;
|
|
9
|
-
}
|
|
10
5
|
export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function DocNodeView(param, ref) {
|
|
11
|
-
let {
|
|
6
|
+
let { as, node, getPos, decorations, innerDecorations, setMount, ...elementProps } = param;
|
|
12
7
|
const innerRef = useRef(null);
|
|
13
|
-
useImperativeHandle(ref, ()=>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
useImperativeHandle(ref, ()=>innerRef.current);
|
|
9
|
+
useImperativeHandle(setMount, ()=>innerRef.current);
|
|
10
|
+
const nodeProps = useMemo(()=>({
|
|
11
|
+
node,
|
|
12
|
+
getPos,
|
|
13
|
+
decorations,
|
|
14
|
+
innerDecorations
|
|
20
15
|
}), [
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
node,
|
|
17
|
+
getPos,
|
|
18
|
+
decorations,
|
|
19
|
+
innerDecorations
|
|
23
20
|
]);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
innerDecorations: innerDeco
|
|
36
|
-
}))) : /*#__PURE__*/ createElement("div", props, /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
|
|
21
|
+
const { childContextValue } = useNodeViewDescriptor(innerRef, ()=>{
|
|
22
|
+
const dom = innerRef.current;
|
|
23
|
+
return {
|
|
24
|
+
dom,
|
|
25
|
+
contentDOM: dom,
|
|
26
|
+
update () {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}, nodeProps);
|
|
31
|
+
const children = /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
|
|
37
32
|
value: childContextValue
|
|
38
33
|
}, /*#__PURE__*/ React.createElement(ChildNodeViews, {
|
|
39
34
|
getPos: getPos,
|
|
40
35
|
node: node,
|
|
41
|
-
innerDecorations:
|
|
42
|
-
}))
|
|
43
|
-
|
|
36
|
+
innerDecorations: innerDecorations
|
|
37
|
+
}));
|
|
38
|
+
const props = {
|
|
39
|
+
...elementProps,
|
|
40
|
+
suppressContentEditableWarning: true,
|
|
41
|
+
ref: innerRef
|
|
42
|
+
};
|
|
43
|
+
const element = as ? /*#__PURE__*/ cloneElement(as, props, children) : /*#__PURE__*/ createElement("div", props, children);
|
|
44
|
+
return nodeProps.decorations.reduce(wrapInDeco, element);
|
|
44
45
|
}));
|
|
@@ -1,25 +1,35 @@
|
|
|
1
|
-
import React, { memo, useContext } from "react";
|
|
2
|
-
import {
|
|
1
|
+
import React, { memo, useContext, useMemo } from "react";
|
|
2
|
+
import { NodeViewContext } from "../contexts/NodeViewContext.js";
|
|
3
3
|
import { CustomNodeView } from "./CustomNodeView.js";
|
|
4
|
+
import { DefaultNodeView } from "./DefaultNodeView.js";
|
|
4
5
|
import { ReactNodeView } from "./ReactNodeView.js";
|
|
5
|
-
export const NodeView = /*#__PURE__*/ memo(function NodeView(
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
6
|
+
export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
|
|
7
|
+
const { components, constructors } = useContext(NodeViewContext);
|
|
8
|
+
const component = components[props.node.type.name] ?? DefaultNodeView;
|
|
9
|
+
const constructor = constructors[props.node.type.name];
|
|
10
|
+
// Construct a wrapper component so that the node view remounts when either
|
|
11
|
+
// its component or constructor changes. A React node view would remount if
|
|
12
|
+
// its underlying component changed without this wrapper, but a custom node
|
|
13
|
+
// view otherwise uses the same React components for all custom node views.
|
|
14
|
+
const Component = useMemo(()=>{
|
|
15
|
+
if (constructor) {
|
|
16
|
+
return function NodeView(props) {
|
|
17
|
+
return /*#__PURE__*/ React.createElement(CustomNodeView, {
|
|
18
|
+
constructor: constructor,
|
|
19
|
+
...props
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
} else {
|
|
23
|
+
return function NodeView(props) {
|
|
24
|
+
return /*#__PURE__*/ React.createElement(ReactNodeView, {
|
|
25
|
+
component: component,
|
|
26
|
+
...props
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}, [
|
|
31
|
+
constructor,
|
|
32
|
+
component
|
|
33
|
+
]);
|
|
34
|
+
return /*#__PURE__*/ React.createElement(Component, props);
|
|
25
35
|
});
|
|
@@ -7,6 +7,9 @@ import { viewDecorations } from "../decorations/viewDecorations.js";
|
|
|
7
7
|
import { useEditor } from "../hooks/useEditor.js";
|
|
8
8
|
import { LayoutGroup } from "./LayoutGroup.js";
|
|
9
9
|
import { DocNodeViewContext } from "./ProseMirrorDoc.js";
|
|
10
|
+
function getPos() {
|
|
11
|
+
return -1;
|
|
12
|
+
}
|
|
10
13
|
function ProseMirrorInner(param) {
|
|
11
14
|
let { className, children, nodeViews, customNodeViews, ...props } = param;
|
|
12
15
|
const [mount, setMount] = useState(null);
|
|
@@ -14,25 +17,33 @@ function ProseMirrorInner(param) {
|
|
|
14
17
|
...props,
|
|
15
18
|
nodeViews: customNodeViews
|
|
16
19
|
});
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
const nodeViewConstructors = editor.view.nodeViews;
|
|
21
|
+
const nodeViewContextValue = useMemo(()=>{
|
|
22
|
+
return {
|
|
23
|
+
components: {
|
|
24
|
+
...nodeViews
|
|
25
|
+
},
|
|
26
|
+
constructors: nodeViewConstructors
|
|
27
|
+
};
|
|
28
|
+
}, [
|
|
29
|
+
nodeViewConstructors,
|
|
20
30
|
nodeViews
|
|
21
31
|
]);
|
|
22
32
|
const node = state.doc;
|
|
23
|
-
const
|
|
24
|
-
const
|
|
33
|
+
const decorations = computeDocDeco(editor.view);
|
|
34
|
+
const innerDecorations = viewDecorations(editor.view, editor.cursorWrapper);
|
|
25
35
|
const docNodeViewContextValue = useMemo(()=>({
|
|
26
36
|
className,
|
|
27
37
|
setMount,
|
|
28
38
|
node,
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
getPos,
|
|
40
|
+
decorations,
|
|
41
|
+
innerDecorations
|
|
31
42
|
}), [
|
|
32
43
|
className,
|
|
33
44
|
node,
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
decorations,
|
|
46
|
+
innerDecorations
|
|
36
47
|
]);
|
|
37
48
|
return /*#__PURE__*/ React.createElement(EditorContext.Provider, {
|
|
38
49
|
value: editor
|
|
@@ -1,34 +1,13 @@
|
|
|
1
|
-
import React, { createContext, forwardRef, useContext
|
|
2
|
-
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
|
|
1
|
+
import React, { createContext, forwardRef, useContext } from "react";
|
|
3
2
|
import { DocNodeView } from "./DocNodeView.js";
|
|
4
3
|
export const DocNodeViewContext = /*#__PURE__*/ createContext(null);
|
|
5
|
-
function ProseMirrorDoc(param, ref) {
|
|
4
|
+
export const ProseMirrorDoc = /*#__PURE__*/ forwardRef(function ProseMirrorDoc(param, ref) {
|
|
6
5
|
let { as, ...props } = param;
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const viewDescRef = useRef(undefined);
|
|
11
|
-
useImperativeHandle(ref, ()=>{
|
|
12
|
-
return innerRef.current;
|
|
13
|
-
}, []);
|
|
14
|
-
const childContextValue = useMemo(()=>({
|
|
15
|
-
parentRef: viewDescRef,
|
|
16
|
-
siblingsRef: childDescriptors
|
|
17
|
-
}), [
|
|
18
|
-
childDescriptors,
|
|
19
|
-
viewDescRef
|
|
20
|
-
]);
|
|
21
|
-
return /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
|
|
22
|
-
value: childContextValue
|
|
23
|
-
}, /*#__PURE__*/ React.createElement(DocNodeView, {
|
|
24
|
-
ref: (el)=>{
|
|
25
|
-
innerRef.current = el;
|
|
26
|
-
setMount(el);
|
|
27
|
-
},
|
|
6
|
+
const docProps = useContext(DocNodeViewContext);
|
|
7
|
+
return /*#__PURE__*/ React.createElement(DocNodeView, {
|
|
8
|
+
ref: ref,
|
|
28
9
|
...props,
|
|
29
10
|
...docProps,
|
|
30
11
|
as: as
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
const ForwardedProseMirrorDoc = /*#__PURE__*/ forwardRef(ProseMirrorDoc);
|
|
34
|
-
export { ForwardedProseMirrorDoc as ProseMirrorDoc };
|
|
12
|
+
});
|
|
13
|
+
});
|