@handlewithcare/react-prosemirror 2.0.0 → 2.2.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 +29 -5
- package/dist/cjs/components/CustomNodeView.js +80 -4
- package/dist/cjs/components/MarkView.js +6 -3
- package/dist/cjs/components/NodeView.js +13 -133
- package/dist/cjs/components/OutputSpec.js +1 -1
- package/dist/cjs/components/ReactNodeView.js +136 -0
- package/dist/cjs/components/TextNodeView.js +2 -2
- package/dist/cjs/findDOMNode.js +46 -0
- package/dist/cjs/hooks/useEditor.js +14 -3
- package/dist/cjs/hooks/useEditorEffect.js +5 -2
- package/dist/cjs/hooks/useIsNodeSelected.js +21 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/plugins/componentEventListeners.js +1 -1
- package/dist/cjs/plugins/reactKeys.js +1 -1
- package/dist/cjs/selection/SelectionDOMObserver.js +0 -3
- package/dist/cjs/selection/selectionToDOM.js +1 -1
- package/dist/cjs/viewdesc.js +18 -8
- package/dist/esm/components/CustomNodeView.js +82 -6
- package/dist/esm/components/MarkView.js +6 -3
- package/dist/esm/components/NodeView.js +14 -134
- package/dist/esm/components/OutputSpec.js +1 -1
- package/dist/esm/components/ReactNodeView.js +85 -0
- package/dist/esm/components/TextNodeView.js +1 -1
- package/dist/esm/findDOMNode.js +31 -0
- package/dist/esm/hooks/useEditor.js +14 -3
- package/dist/esm/hooks/useEditorEffect.js +5 -2
- package/dist/esm/hooks/useIsNodeSelected.js +11 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugins/componentEventListeners.js +1 -1
- package/dist/esm/plugins/reactKeys.js +1 -1
- package/dist/esm/selection/SelectionDOMObserver.js +0 -3
- package/dist/esm/selection/selectionToDOM.js +1 -1
- package/dist/esm/viewdesc.js +18 -8
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/components/CustomNodeView.d.ts +3 -12
- package/dist/types/components/ReactNodeView.d.ts +11 -0
- package/dist/types/contexts/EditorContext.d.ts +2 -0
- package/dist/types/findDOMNode.d.ts +3 -0
- package/dist/types/hooks/useEditor.d.ts +1 -0
- package/dist/types/hooks/useIsNodeSelected.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/selection/SelectionDOMObserver.d.ts +0 -1
- package/dist/types/viewdesc.d.ts +19 -6
- package/package.json +19 -6
package/README.md
CHANGED
|
@@ -22,16 +22,21 @@ ProseMirror renderer will happen in this repository, published as
|
|
|
22
22
|
|
|
23
23
|
## Installation
|
|
24
24
|
|
|
25
|
+
_Note_: React ProseMirror releases are coupled to specific prosemirror-view
|
|
26
|
+
releases, and are not guaranteed to work with other versions of
|
|
27
|
+
prosemirror-view. Ensure that your version of prosemirror-view matches the
|
|
28
|
+
version in React ProseMirror's peer dependencies!
|
|
29
|
+
|
|
25
30
|
npm:
|
|
26
31
|
|
|
27
32
|
```sh
|
|
28
|
-
npm install @handlewithcare/react-prosemirror
|
|
33
|
+
npm install @handlewithcare/react-prosemirror prosemirror-view@1.37.1 prosemirror-state prosemirror-model
|
|
29
34
|
```
|
|
30
35
|
|
|
31
36
|
yarn:
|
|
32
37
|
|
|
33
38
|
```sh
|
|
34
|
-
yarn add @handlewithcare/react-prosemirror
|
|
39
|
+
yarn add @handlewithcare/react-prosemirror prosemirror-view@1.37.1 prosemirror-state prosemirror-model
|
|
35
40
|
```
|
|
36
41
|
|
|
37
42
|
<!-- toc -->
|
|
@@ -43,7 +48,7 @@ yarn add @handlewithcare/react-prosemirror
|
|
|
43
48
|
- [`useEditorEventCallback`](#useeditoreventcallback)
|
|
44
49
|
- [`useEditorEventListener`](#useeditoreventlistener)
|
|
45
50
|
- [Building node views with React](#building-node-views-with-react)
|
|
46
|
-
- [What's
|
|
51
|
+
- [What's new in v2?](#whats-new-in-v2)
|
|
47
52
|
- [API changes](#api-changes)
|
|
48
53
|
- [API](#api)
|
|
49
54
|
- [`ProseMirror`](#prosemirror)
|
|
@@ -55,7 +60,9 @@ yarn add @handlewithcare/react-prosemirror
|
|
|
55
60
|
- [`NodeViewComponentProps`](#nodeviewcomponentprops)
|
|
56
61
|
- [`useStopEvent`](#usestopevent)
|
|
57
62
|
- [`useSelectNode`](#useselectnode)
|
|
63
|
+
- [`useIsNodeSelected`](#useisnodeselected)
|
|
58
64
|
- [`widget`](#widget)
|
|
65
|
+
- [Looking for someone to collaborate with?](#looking-for-someone-to-collaborate-with)
|
|
59
66
|
|
|
60
67
|
<!-- tocstop -->
|
|
61
68
|
|
|
@@ -416,9 +423,9 @@ function ProseMirrorEditor() {
|
|
|
416
423
|
}
|
|
417
424
|
```
|
|
418
425
|
|
|
419
|
-
## What's
|
|
426
|
+
## What's new in v2?
|
|
420
427
|
|
|
421
|
-
The
|
|
428
|
+
The v2 release constitutes a significant re-write of the library.
|
|
422
429
|
|
|
423
430
|
Previously, React ProseMirror relied on ProseMirror's EditorView to manage the
|
|
424
431
|
DOM for the editor. To integrate it with React, we used React
|
|
@@ -689,6 +696,16 @@ This hook can be used within a node view component to register
|
|
|
689
696
|
The selectNode handler will only be called when a NodeSelection is created whose
|
|
690
697
|
node is this one.
|
|
691
698
|
|
|
699
|
+
### `useIsNodeSelected`
|
|
700
|
+
|
|
701
|
+
```tsx
|
|
702
|
+
type useIsNodeSelected = (): boolean
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
This hook can be used within a node view component to subscribe to a boolean
|
|
706
|
+
value determining whether this node is selected. The hook will return true when
|
|
707
|
+
a NodeSelection is created whose node is this one.
|
|
708
|
+
|
|
692
709
|
### `widget`
|
|
693
710
|
|
|
694
711
|
```tsx
|
|
@@ -703,3 +720,10 @@ type widget = (
|
|
|
703
720
|
|
|
704
721
|
Like ProseMirror View's `Decoration.widget`, but with support for React
|
|
705
722
|
components.
|
|
723
|
+
|
|
724
|
+
## Looking for someone to collaborate with?
|
|
725
|
+
|
|
726
|
+
Reach out to [Handle with Care](https://handlewithcare.dev/#get-in-touch)! We're
|
|
727
|
+
a product development collective with years of experience bringing excellent
|
|
728
|
+
ideas to life. We love React and ProseMirror, and we're always looking for new
|
|
729
|
+
folks to work with!
|
|
@@ -10,8 +10,10 @@ Object.defineProperty(exports, "CustomNodeView", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
12
|
const _reactdom = require("react-dom");
|
|
13
|
+
const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
|
|
13
14
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
14
15
|
const _useClientOnly = require("../hooks/useClientOnly.js");
|
|
16
|
+
const _useNodeViewDescriptor = require("../hooks/useNodeViewDescriptor.js");
|
|
15
17
|
const _ChildNodeViews = require("./ChildNodeViews.js");
|
|
16
18
|
function _getRequireWildcardCache(nodeInterop) {
|
|
17
19
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -54,10 +56,75 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
54
56
|
}
|
|
55
57
|
return newObj;
|
|
56
58
|
}
|
|
57
|
-
function CustomNodeView(param) {
|
|
58
|
-
let {
|
|
59
|
+
const CustomNodeView = /*#__PURE__*/ (0, _react.memo)(function CustomNodeView(param) {
|
|
60
|
+
let { customNodeView, node, getPos, innerDeco, outerDeco } = param;
|
|
59
61
|
const { view } = (0, _react.useContext)(_EditorContext.EditorContext);
|
|
62
|
+
const domRef = (0, _react.useRef)(null);
|
|
63
|
+
const nodeDomRef = (0, _react.useRef)(null);
|
|
64
|
+
const contentDomRef = (0, _react.useRef)(null);
|
|
65
|
+
const getPosFunc = (0, _react.useRef)(()=>getPos.current()).current;
|
|
66
|
+
// this is ill-conceived; should revisit
|
|
67
|
+
const initialNode = (0, _react.useRef)(node);
|
|
68
|
+
const initialOuterDeco = (0, _react.useRef)(outerDeco);
|
|
69
|
+
const initialInnerDeco = (0, _react.useRef)(innerDeco);
|
|
70
|
+
const customNodeViewRootRef = (0, _react.useRef)(null);
|
|
71
|
+
const customNodeViewRef = (0, _react.useRef)(null);
|
|
60
72
|
const shouldRender = (0, _useClientOnly.useClientOnly)();
|
|
73
|
+
(0, _react.useLayoutEffect)(()=>{
|
|
74
|
+
if (!customNodeViewRef.current || !customNodeViewRootRef.current || !shouldRender) return;
|
|
75
|
+
const { dom } = customNodeViewRef.current;
|
|
76
|
+
nodeDomRef.current = customNodeViewRootRef.current;
|
|
77
|
+
customNodeViewRootRef.current.appendChild(dom);
|
|
78
|
+
return ()=>{
|
|
79
|
+
customNodeViewRef.current?.destroy?.();
|
|
80
|
+
};
|
|
81
|
+
}, [
|
|
82
|
+
customNodeViewRef,
|
|
83
|
+
customNodeViewRootRef,
|
|
84
|
+
nodeDomRef,
|
|
85
|
+
shouldRender
|
|
86
|
+
]);
|
|
87
|
+
(0, _react.useLayoutEffect)(()=>{
|
|
88
|
+
if (!customNodeView || !customNodeViewRef.current || !shouldRender) return;
|
|
89
|
+
const { destroy, update } = customNodeViewRef.current;
|
|
90
|
+
const updated = update?.call(customNodeViewRef.current, node, outerDeco, innerDeco) ?? true;
|
|
91
|
+
if (updated) return;
|
|
92
|
+
destroy?.call(customNodeViewRef.current);
|
|
93
|
+
if (!customNodeViewRootRef.current) return;
|
|
94
|
+
initialNode.current = node;
|
|
95
|
+
initialOuterDeco.current = outerDeco;
|
|
96
|
+
initialInnerDeco.current = innerDeco;
|
|
97
|
+
customNodeViewRef.current = customNodeView(initialNode.current, // customNodeView will only be set if view is set, and we can only reach
|
|
98
|
+
// this line if customNodeView is set
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
100
|
+
view, getPosFunc, initialOuterDeco.current, initialInnerDeco.current);
|
|
101
|
+
const { dom } = customNodeViewRef.current;
|
|
102
|
+
nodeDomRef.current = customNodeViewRootRef.current;
|
|
103
|
+
customNodeViewRootRef.current.appendChild(dom);
|
|
104
|
+
}, [
|
|
105
|
+
customNodeView,
|
|
106
|
+
view,
|
|
107
|
+
innerDeco,
|
|
108
|
+
node,
|
|
109
|
+
outerDeco,
|
|
110
|
+
getPos,
|
|
111
|
+
customNodeViewRef,
|
|
112
|
+
customNodeViewRootRef,
|
|
113
|
+
initialNode,
|
|
114
|
+
initialOuterDeco,
|
|
115
|
+
initialInnerDeco,
|
|
116
|
+
nodeDomRef,
|
|
117
|
+
shouldRender,
|
|
118
|
+
getPosFunc
|
|
119
|
+
]);
|
|
120
|
+
const { childDescriptors, nodeViewDescRef } = (0, _useNodeViewDescriptor.useNodeViewDescriptor)(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
|
|
121
|
+
const childContextValue = (0, _react.useMemo)(()=>({
|
|
122
|
+
parentRef: nodeViewDescRef,
|
|
123
|
+
siblingsRef: childDescriptors
|
|
124
|
+
}), [
|
|
125
|
+
childDescriptors,
|
|
126
|
+
nodeViewDescRef
|
|
127
|
+
]);
|
|
61
128
|
if (!shouldRender) return null;
|
|
62
129
|
if (!customNodeViewRef.current) {
|
|
63
130
|
customNodeViewRef.current = customNodeView(initialNode.current, // customNodeView will only be set if view is set, and we can only reach
|
|
@@ -67,7 +134,7 @@ function CustomNodeView(param) {
|
|
|
67
134
|
}
|
|
68
135
|
const { contentDOM } = customNodeViewRef.current;
|
|
69
136
|
contentDomRef.current = contentDOM ?? null;
|
|
70
|
-
|
|
137
|
+
const element = /*#__PURE__*/ (0, _react.createElement)(node.isInline ? "span" : "div", {
|
|
71
138
|
ref: customNodeViewRootRef,
|
|
72
139
|
contentEditable: !!contentDOM,
|
|
73
140
|
suppressContentEditableWarning: true
|
|
@@ -76,4 +143,13 @@ function CustomNodeView(param) {
|
|
|
76
143
|
node: node,
|
|
77
144
|
innerDecorations: innerDeco
|
|
78
145
|
}), contentDOM));
|
|
79
|
-
|
|
146
|
+
const decoratedElement = /*#__PURE__*/ (0, _react.cloneElement)(outerDeco.reduce(_ChildNodeViews.wrapInDeco, element), // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
147
|
+
outerDeco.some((d)=>d.type.attrs.nodeName) ? {
|
|
148
|
+
ref: domRef
|
|
149
|
+
} : // we've already passed the domRef to the NodeView component
|
|
150
|
+
// as a prop
|
|
151
|
+
undefined);
|
|
152
|
+
return /*#__PURE__*/ _react.default.createElement(_ChildDescriptorsContext.ChildDescriptorsContext.Provider, {
|
|
153
|
+
value: childContextValue
|
|
154
|
+
}, decoratedElement);
|
|
155
|
+
});
|
|
@@ -82,12 +82,15 @@ const MarkView = /*#__PURE__*/ (0, _react.memo)(/*#__PURE__*/ (0, _react.forward
|
|
|
82
82
|
if (!domRef.current) return;
|
|
83
83
|
const firstChildDesc = childDescriptors.current[0];
|
|
84
84
|
if (!viewDescRef.current) {
|
|
85
|
-
viewDescRef.current = new _viewdesc.MarkViewDesc(parentRef.current, childDescriptors.current, ()=>getPos.current(), mark, domRef.current, firstChildDesc?.dom.parentElement ?? domRef.current
|
|
85
|
+
viewDescRef.current = new _viewdesc.MarkViewDesc(parentRef.current, childDescriptors.current, ()=>getPos.current(), mark, domRef.current, firstChildDesc?.dom.parentElement ?? domRef.current, {
|
|
86
|
+
dom: domRef.current,
|
|
87
|
+
contentDOM: firstChildDesc?.dom.parentElement ?? domRef.current
|
|
88
|
+
});
|
|
86
89
|
} else {
|
|
87
90
|
viewDescRef.current.parent = parentRef.current;
|
|
88
|
-
viewDescRef.current.dom = domRef.current;
|
|
91
|
+
viewDescRef.current.spec.dom = viewDescRef.current.dom = domRef.current;
|
|
89
92
|
viewDescRef.current.children = childDescriptors.current;
|
|
90
|
-
viewDescRef.current.contentDOM = firstChildDesc?.dom.parentElement ?? domRef.current;
|
|
93
|
+
viewDescRef.current.spec.contentDOM = viewDescRef.current.contentDOM = firstChildDesc?.dom.parentElement ?? domRef.current;
|
|
91
94
|
viewDescRef.current.mark = mark;
|
|
92
95
|
viewDescRef.current.getPos = ()=>getPos.current();
|
|
93
96
|
}
|
|
@@ -9,15 +9,9 @@ Object.defineProperty(exports, "NodeView", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
|
-
const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
|
|
13
12
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
14
|
-
const _NodeViewContext = require("../contexts/NodeViewContext.js");
|
|
15
|
-
const _SelectNodeContext = require("../contexts/SelectNodeContext.js");
|
|
16
|
-
const _StopEventContext = require("../contexts/StopEventContext.js");
|
|
17
|
-
const _useNodeViewDescriptor = require("../hooks/useNodeViewDescriptor.js");
|
|
18
|
-
const _ChildNodeViews = require("./ChildNodeViews.js");
|
|
19
13
|
const _CustomNodeView = require("./CustomNodeView.js");
|
|
20
|
-
const
|
|
14
|
+
const _ReactNodeView = require("./ReactNodeView.js");
|
|
21
15
|
function _getRequireWildcardCache(nodeInterop) {
|
|
22
16
|
if (typeof WeakMap !== "function") return null;
|
|
23
17
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -61,136 +55,22 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
61
55
|
}
|
|
62
56
|
const NodeView = /*#__PURE__*/ (0, _react.memo)(function NodeView(param) {
|
|
63
57
|
let { outerDeco, getPos, node, innerDeco, ...props } = param;
|
|
64
|
-
const domRef = (0, _react.useRef)(null);
|
|
65
|
-
const nodeDomRef = (0, _react.useRef)(null);
|
|
66
|
-
const contentDomRef = (0, _react.useRef)(null);
|
|
67
|
-
const getPosFunc = (0, _react.useRef)(()=>getPos.current()).current;
|
|
68
|
-
// this is ill-conceived; should revisit
|
|
69
|
-
const initialNode = (0, _react.useRef)(node);
|
|
70
|
-
const initialOuterDeco = (0, _react.useRef)(outerDeco);
|
|
71
|
-
const initialInnerDeco = (0, _react.useRef)(innerDeco);
|
|
72
|
-
const customNodeViewRootRef = (0, _react.useRef)(null);
|
|
73
|
-
const customNodeViewRef = (0, _react.useRef)(null);
|
|
74
|
-
// const state = useEditorState();
|
|
75
|
-
const { nodeViews } = (0, _react.useContext)(_NodeViewContext.NodeViewContext);
|
|
76
58
|
const { view } = (0, _react.useContext)(_EditorContext.EditorContext);
|
|
77
|
-
let element = null;
|
|
78
|
-
const Component = nodeViews[node.type.name];
|
|
79
|
-
const outputSpec = (0, _react.useMemo)(()=>node.type.spec.toDOM?.(node), [
|
|
80
|
-
node
|
|
81
|
-
]);
|
|
82
|
-
// TODO: Would be great to pull all of the custom node view stuff into
|
|
83
|
-
// a hook
|
|
84
59
|
const customNodeView = view?.someProp("nodeViews", (nodeViews)=>nodeViews?.[node.type.name]);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const { dom } = customNodeViewRef.current;
|
|
88
|
-
nodeDomRef.current = customNodeViewRootRef.current;
|
|
89
|
-
customNodeViewRootRef.current.appendChild(dom);
|
|
90
|
-
return ()=>{
|
|
91
|
-
customNodeViewRef.current?.destroy?.();
|
|
92
|
-
};
|
|
93
|
-
}, []);
|
|
94
|
-
(0, _react.useLayoutEffect)(()=>{
|
|
95
|
-
if (!customNodeView || !customNodeViewRef.current) return;
|
|
96
|
-
const { destroy, update } = customNodeViewRef.current;
|
|
97
|
-
const updated = update?.call(customNodeViewRef.current, node, outerDeco, innerDeco) ?? true;
|
|
98
|
-
if (updated) return;
|
|
99
|
-
destroy?.call(customNodeViewRef.current);
|
|
100
|
-
if (!customNodeViewRootRef.current) return;
|
|
101
|
-
initialNode.current = node;
|
|
102
|
-
initialOuterDeco.current = outerDeco;
|
|
103
|
-
initialInnerDeco.current = innerDeco;
|
|
104
|
-
customNodeViewRef.current = customNodeView(initialNode.current, // customNodeView will only be set if view is set, and we can only reach
|
|
105
|
-
// this line if customNodeView is set
|
|
106
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
107
|
-
view, ()=>getPos.current(), initialOuterDeco.current, initialInnerDeco.current);
|
|
108
|
-
const { dom } = customNodeViewRef.current;
|
|
109
|
-
nodeDomRef.current = customNodeViewRootRef.current;
|
|
110
|
-
customNodeViewRootRef.current.appendChild(dom);
|
|
111
|
-
}, [
|
|
112
|
-
customNodeView,
|
|
113
|
-
view,
|
|
114
|
-
innerDeco,
|
|
115
|
-
node,
|
|
116
|
-
outerDeco,
|
|
117
|
-
getPos
|
|
118
|
-
]);
|
|
119
|
-
const { hasContentDOM, childDescriptors, setStopEvent, setSelectNode, nodeViewDescRef } = (0, _useNodeViewDescriptor.useNodeViewDescriptor)(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
|
|
120
|
-
const finalProps = {
|
|
121
|
-
...props,
|
|
122
|
-
...!hasContentDOM && {
|
|
123
|
-
contentEditable: false
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
const nodeProps = (0, _react.useMemo)(()=>({
|
|
127
|
-
node: node,
|
|
128
|
-
getPos: getPosFunc,
|
|
129
|
-
decorations: outerDeco,
|
|
130
|
-
innerDecorations: innerDeco
|
|
131
|
-
}), [
|
|
132
|
-
getPosFunc,
|
|
133
|
-
innerDeco,
|
|
134
|
-
node,
|
|
135
|
-
outerDeco
|
|
136
|
-
]);
|
|
137
|
-
if (Component) {
|
|
138
|
-
element = /*#__PURE__*/ _react.default.createElement(Component, {
|
|
139
|
-
...finalProps,
|
|
140
|
-
ref: nodeDomRef,
|
|
141
|
-
nodeProps: nodeProps
|
|
142
|
-
}, /*#__PURE__*/ _react.default.createElement(_ChildNodeViews.ChildNodeViews, {
|
|
143
|
-
getPos: getPos,
|
|
144
|
-
node: node,
|
|
145
|
-
innerDecorations: innerDeco
|
|
146
|
-
}));
|
|
147
|
-
} else if (customNodeView) {
|
|
148
|
-
element = /*#__PURE__*/ _react.default.createElement(_CustomNodeView.CustomNodeView, {
|
|
149
|
-
contentDomRef: contentDomRef,
|
|
60
|
+
if (customNodeView) {
|
|
61
|
+
return /*#__PURE__*/ _react.default.createElement(_CustomNodeView.CustomNodeView, {
|
|
150
62
|
customNodeView: customNodeView,
|
|
151
|
-
customNodeViewRef: customNodeViewRef,
|
|
152
|
-
customNodeViewRootRef: customNodeViewRootRef,
|
|
153
|
-
initialInnerDeco: initialInnerDeco,
|
|
154
|
-
initialNode: initialNode,
|
|
155
|
-
initialOuterDeco: initialOuterDeco,
|
|
156
63
|
node: node,
|
|
157
|
-
|
|
158
|
-
|
|
64
|
+
innerDeco: innerDeco,
|
|
65
|
+
outerDeco: outerDeco,
|
|
66
|
+
getPos: getPos
|
|
159
67
|
});
|
|
160
|
-
} else {
|
|
161
|
-
if (outputSpec) {
|
|
162
|
-
element = /*#__PURE__*/ _react.default.createElement(_OutputSpec.OutputSpec, {
|
|
163
|
-
...finalProps,
|
|
164
|
-
ref: nodeDomRef,
|
|
165
|
-
outputSpec: outputSpec
|
|
166
|
-
}, /*#__PURE__*/ _react.default.createElement(_ChildNodeViews.ChildNodeViews, {
|
|
167
|
-
getPos: getPos,
|
|
168
|
-
node: node,
|
|
169
|
-
innerDecorations: innerDeco
|
|
170
|
-
}));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (!element) {
|
|
174
|
-
throw new Error(`Node spec for ${node.type.name} is missing toDOM`);
|
|
175
68
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
parentRef: nodeViewDescRef,
|
|
184
|
-
siblingsRef: childDescriptors
|
|
185
|
-
}), [
|
|
186
|
-
childDescriptors,
|
|
187
|
-
nodeViewDescRef
|
|
188
|
-
]);
|
|
189
|
-
return /*#__PURE__*/ _react.default.createElement(_SelectNodeContext.SelectNodeContext.Provider, {
|
|
190
|
-
value: setSelectNode
|
|
191
|
-
}, /*#__PURE__*/ _react.default.createElement(_StopEventContext.StopEventContext.Provider, {
|
|
192
|
-
value: setStopEvent
|
|
193
|
-
}, /*#__PURE__*/ _react.default.createElement(_ChildDescriptorsContext.ChildDescriptorsContext.Provider, {
|
|
194
|
-
value: childContextValue
|
|
195
|
-
}, decoratedElement)));
|
|
69
|
+
return /*#__PURE__*/ _react.default.createElement(_ReactNodeView.ReactNodeView, {
|
|
70
|
+
node: node,
|
|
71
|
+
innerDeco: innerDeco,
|
|
72
|
+
outerDeco: outerDeco,
|
|
73
|
+
getPos: getPos,
|
|
74
|
+
...props
|
|
75
|
+
});
|
|
196
76
|
});
|
|
@@ -57,7 +57,7 @@ const ForwardedOutputSpec = /*#__PURE__*/ (0, _react.memo)(/*#__PURE__*/ (0, _re
|
|
|
57
57
|
return /*#__PURE__*/ _react.default.createElement(_react.default.Fragment, null, outputSpec);
|
|
58
58
|
}
|
|
59
59
|
if (!Array.isArray(outputSpec)) {
|
|
60
|
-
throw new Error("@
|
|
60
|
+
throw new Error("@handlewithcare/react-prosemirror only supports strings and arrays in toDOM");
|
|
61
61
|
}
|
|
62
62
|
const tagSpec = outputSpec[0];
|
|
63
63
|
const tagName = tagSpec.replace(" ", ":");
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "ReactNodeView", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return ReactNodeView;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
12
|
+
const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
|
|
13
|
+
const _NodeViewContext = require("../contexts/NodeViewContext.js");
|
|
14
|
+
const _SelectNodeContext = require("../contexts/SelectNodeContext.js");
|
|
15
|
+
const _StopEventContext = require("../contexts/StopEventContext.js");
|
|
16
|
+
const _useNodeViewDescriptor = require("../hooks/useNodeViewDescriptor.js");
|
|
17
|
+
const _ChildNodeViews = require("./ChildNodeViews.js");
|
|
18
|
+
const _OutputSpec = require("./OutputSpec.js");
|
|
19
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
20
|
+
if (typeof WeakMap !== "function") return null;
|
|
21
|
+
var cacheBabelInterop = new WeakMap();
|
|
22
|
+
var cacheNodeInterop = new WeakMap();
|
|
23
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
24
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
25
|
+
})(nodeInterop);
|
|
26
|
+
}
|
|
27
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
28
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
29
|
+
return obj;
|
|
30
|
+
}
|
|
31
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
32
|
+
return {
|
|
33
|
+
default: obj
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
37
|
+
if (cache && cache.has(obj)) {
|
|
38
|
+
return cache.get(obj);
|
|
39
|
+
}
|
|
40
|
+
var newObj = {
|
|
41
|
+
__proto__: null
|
|
42
|
+
};
|
|
43
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
44
|
+
for(var key in obj){
|
|
45
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
46
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
47
|
+
if (desc && (desc.get || desc.set)) {
|
|
48
|
+
Object.defineProperty(newObj, key, desc);
|
|
49
|
+
} else {
|
|
50
|
+
newObj[key] = obj[key];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
newObj.default = obj;
|
|
55
|
+
if (cache) {
|
|
56
|
+
cache.set(obj, newObj);
|
|
57
|
+
}
|
|
58
|
+
return newObj;
|
|
59
|
+
}
|
|
60
|
+
const ReactNodeView = /*#__PURE__*/ (0, _react.memo)(function ReactNodeView(param) {
|
|
61
|
+
let { outerDeco, getPos, node, innerDeco, ...props } = param;
|
|
62
|
+
const domRef = (0, _react.useRef)(null);
|
|
63
|
+
const nodeDomRef = (0, _react.useRef)(null);
|
|
64
|
+
const contentDomRef = (0, _react.useRef)(null);
|
|
65
|
+
const getPosFunc = (0, _react.useRef)(()=>getPos.current()).current;
|
|
66
|
+
const { nodeViews } = (0, _react.useContext)(_NodeViewContext.NodeViewContext);
|
|
67
|
+
let element = null;
|
|
68
|
+
const Component = nodeViews[node.type.name];
|
|
69
|
+
const outputSpec = (0, _react.useMemo)(()=>node.type.spec.toDOM?.(node), [
|
|
70
|
+
node
|
|
71
|
+
]);
|
|
72
|
+
const { hasContentDOM, childDescriptors, setStopEvent, setSelectNode, nodeViewDescRef } = (0, _useNodeViewDescriptor.useNodeViewDescriptor)(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
|
|
73
|
+
const finalProps = {
|
|
74
|
+
...props,
|
|
75
|
+
...!hasContentDOM && {
|
|
76
|
+
contentEditable: false
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const nodeProps = (0, _react.useMemo)(()=>({
|
|
80
|
+
node: node,
|
|
81
|
+
getPos: getPosFunc,
|
|
82
|
+
decorations: outerDeco,
|
|
83
|
+
innerDecorations: innerDeco
|
|
84
|
+
}), [
|
|
85
|
+
getPosFunc,
|
|
86
|
+
innerDeco,
|
|
87
|
+
node,
|
|
88
|
+
outerDeco
|
|
89
|
+
]);
|
|
90
|
+
if (Component) {
|
|
91
|
+
element = /*#__PURE__*/ _react.default.createElement(Component, {
|
|
92
|
+
...finalProps,
|
|
93
|
+
ref: nodeDomRef,
|
|
94
|
+
nodeProps: nodeProps
|
|
95
|
+
}, /*#__PURE__*/ _react.default.createElement(_ChildNodeViews.ChildNodeViews, {
|
|
96
|
+
getPos: getPos,
|
|
97
|
+
node: node,
|
|
98
|
+
innerDecorations: innerDeco
|
|
99
|
+
}));
|
|
100
|
+
} else {
|
|
101
|
+
if (outputSpec) {
|
|
102
|
+
element = /*#__PURE__*/ _react.default.createElement(_OutputSpec.OutputSpec, {
|
|
103
|
+
...finalProps,
|
|
104
|
+
ref: nodeDomRef,
|
|
105
|
+
outputSpec: outputSpec
|
|
106
|
+
}, /*#__PURE__*/ _react.default.createElement(_ChildNodeViews.ChildNodeViews, {
|
|
107
|
+
getPos: getPos,
|
|
108
|
+
node: node,
|
|
109
|
+
innerDecorations: innerDeco
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!element) {
|
|
114
|
+
throw new Error(`Node spec for ${node.type.name} is missing toDOM`);
|
|
115
|
+
}
|
|
116
|
+
const decoratedElement = /*#__PURE__*/ (0, _react.cloneElement)(outerDeco.reduce(_ChildNodeViews.wrapInDeco, element), // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
117
|
+
outerDeco.some((d)=>d.type.attrs.nodeName) ? {
|
|
118
|
+
ref: domRef
|
|
119
|
+
} : // we've already passed the domRef to the NodeView component
|
|
120
|
+
// as a prop
|
|
121
|
+
undefined);
|
|
122
|
+
const childContextValue = (0, _react.useMemo)(()=>({
|
|
123
|
+
parentRef: nodeViewDescRef,
|
|
124
|
+
siblingsRef: childDescriptors
|
|
125
|
+
}), [
|
|
126
|
+
childDescriptors,
|
|
127
|
+
nodeViewDescRef
|
|
128
|
+
]);
|
|
129
|
+
return /*#__PURE__*/ _react.default.createElement(_SelectNodeContext.SelectNodeContext.Provider, {
|
|
130
|
+
value: setSelectNode
|
|
131
|
+
}, /*#__PURE__*/ _react.default.createElement(_StopEventContext.StopEventContext.Provider, {
|
|
132
|
+
value: setStopEvent
|
|
133
|
+
}, /*#__PURE__*/ _react.default.createElement(_ChildDescriptorsContext.ChildDescriptorsContext.Provider, {
|
|
134
|
+
value: childContextValue
|
|
135
|
+
}, decoratedElement)));
|
|
136
|
+
});
|
|
@@ -10,7 +10,7 @@ Object.defineProperty(exports, "TextNodeView", {
|
|
|
10
10
|
});
|
|
11
11
|
const _prosemirrorview = require("prosemirror-view");
|
|
12
12
|
const _react = require("react");
|
|
13
|
-
const
|
|
13
|
+
const _findDOMNode = require("../findDOMNode.js");
|
|
14
14
|
const _viewdesc = require("../viewdesc.js");
|
|
15
15
|
const _ChildNodeViews = require("./ChildNodeViews.js");
|
|
16
16
|
function shallowEqual(objA, objB) {
|
|
@@ -42,7 +42,7 @@ let TextNodeView = class TextNodeView extends _react.Component {
|
|
|
42
42
|
const { view, decorations, siblingsRef, parentRef, getPos, node } = this.props;
|
|
43
43
|
// There simply is no other way to ref a text node
|
|
44
44
|
// eslint-disable-next-line react/no-find-dom-node
|
|
45
|
-
const dom = (0,
|
|
45
|
+
const dom = (0, _findDOMNode.findDOMNode)(this);
|
|
46
46
|
// We only need to explicitly create a CompositionViewDesc
|
|
47
47
|
// when a composition was started that produces a new text node.
|
|
48
48
|
// Otherwise we just rely on re-rendering the renderRef
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
findDOMNode: function() {
|
|
13
|
+
return findDOMNode;
|
|
14
|
+
},
|
|
15
|
+
getInstance: function() {
|
|
16
|
+
return getInstance;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const _reflection = require("react-reconciler/reflection");
|
|
20
|
+
function getInstance(key) {
|
|
21
|
+
return key._reactInternals;
|
|
22
|
+
}
|
|
23
|
+
// https://github.com/facebook/react/blob/main/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js#L322
|
|
24
|
+
function getPublicInstance(instance) {
|
|
25
|
+
return instance;
|
|
26
|
+
}
|
|
27
|
+
// https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberReconciler.js#L153
|
|
28
|
+
function findHostInstance(component) {
|
|
29
|
+
const fiber = getInstance(component);
|
|
30
|
+
if (fiber === undefined) {
|
|
31
|
+
if (typeof component.render === "function") {
|
|
32
|
+
throw new Error("Unable to find node on an unmounted component.");
|
|
33
|
+
} else {
|
|
34
|
+
const keys = Object.keys(component).join(",");
|
|
35
|
+
throw new Error(`Argument appears to not be a ReactComponent. Keys: ${keys}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const hostFiber = (0, _reflection.findCurrentHostFiber)(fiber);
|
|
39
|
+
if (hostFiber === null) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return getPublicInstance(hostFiber.stateNode);
|
|
43
|
+
}
|
|
44
|
+
function findDOMNode(componentOrElement) {
|
|
45
|
+
return findHostInstance(componentOrElement);
|
|
46
|
+
}
|
|
@@ -180,6 +180,7 @@ function useEditor(mount, options) {
|
|
|
180
180
|
didWarnValueDefaultValue = true;
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
+
const flushSyncRef = (0, _react.useRef)(true);
|
|
183
184
|
const [cursorWrapper, _setCursorWrapper] = (0, _react.useState)(null);
|
|
184
185
|
const forceUpdate = (0, _useForceUpdate.useForceUpdate)();
|
|
185
186
|
const defaultState = options.defaultState ?? EMPTY_STATE;
|
|
@@ -201,14 +202,23 @@ function useEditor(mount, options) {
|
|
|
201
202
|
setCursorWrapper
|
|
202
203
|
]);
|
|
203
204
|
const dispatchTransaction = (0, _react.useCallback)(function dispatchTransaction(tr) {
|
|
204
|
-
(
|
|
205
|
+
if (flushSyncRef.current) {
|
|
206
|
+
(0, _reactdom.flushSync)(()=>{
|
|
207
|
+
if (!options.state) {
|
|
208
|
+
setState((s)=>s.apply(tr));
|
|
209
|
+
}
|
|
210
|
+
if (options.dispatchTransaction) {
|
|
211
|
+
options.dispatchTransaction.call(this, tr);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
205
215
|
if (!options.state) {
|
|
206
216
|
setState((s)=>s.apply(tr));
|
|
207
217
|
}
|
|
208
218
|
if (options.dispatchTransaction) {
|
|
209
219
|
options.dispatchTransaction.call(this, tr);
|
|
210
220
|
}
|
|
211
|
-
}
|
|
221
|
+
}
|
|
212
222
|
}, [
|
|
213
223
|
options.dispatchTransaction,
|
|
214
224
|
options.state
|
|
@@ -273,7 +283,8 @@ function useEditor(mount, options) {
|
|
|
273
283
|
registerEventListener,
|
|
274
284
|
unregisterEventListener,
|
|
275
285
|
cursorWrapper,
|
|
276
|
-
docViewDescRef
|
|
286
|
+
docViewDescRef,
|
|
287
|
+
flushSyncRef
|
|
277
288
|
}), [
|
|
278
289
|
view,
|
|
279
290
|
registerEventListener,
|
|
@@ -12,7 +12,7 @@ const _react = require("react");
|
|
|
12
12
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
13
13
|
const _useLayoutGroupEffect = require("./useLayoutGroupEffect.js");
|
|
14
14
|
function useEditorEffect(effect, dependencies) {
|
|
15
|
-
const { view } = (0, _react.useContext)(_EditorContext.EditorContext);
|
|
15
|
+
const { view, flushSyncRef } = (0, _react.useContext)(_EditorContext.EditorContext);
|
|
16
16
|
// The rules of hooks want `effect` to be included in the
|
|
17
17
|
// dependency list, but dependency issues for `effect` will
|
|
18
18
|
// be caught by the linter at the call-site for
|
|
@@ -22,7 +22,10 @@ function useEditorEffect(effect, dependencies) {
|
|
|
22
22
|
// be defined inline and run on every re-render.
|
|
23
23
|
(0, _useLayoutGroupEffect.useLayoutGroupEffect)(()=>{
|
|
24
24
|
if (view) {
|
|
25
|
-
|
|
25
|
+
flushSyncRef.current = false;
|
|
26
|
+
const result = effect(view);
|
|
27
|
+
flushSyncRef.current = true;
|
|
28
|
+
return result;
|
|
26
29
|
}
|
|
27
30
|
}, // The rules of hooks want to be able to statically
|
|
28
31
|
// verify the dependencies for the effect, but this will
|