@handlewithcare/react-prosemirror 2.1.0 → 2.2.1

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.
Files changed (34) hide show
  1. package/README.md +22 -3
  2. package/dist/cjs/components/CustomNodeView.js +80 -4
  3. package/dist/cjs/components/NodeView.js +13 -133
  4. package/dist/cjs/components/OutputSpec.js +1 -1
  5. package/dist/cjs/components/ReactNodeView.js +136 -0
  6. package/dist/cjs/components/TextNodeView.js +2 -2
  7. package/dist/cjs/findDOMNode.js +46 -0
  8. package/dist/cjs/hooks/useEditor.js +14 -3
  9. package/dist/cjs/hooks/useEditorEffect.js +5 -2
  10. package/dist/cjs/hooks/useIsNodeSelected.js +21 -0
  11. package/dist/cjs/index.js +4 -0
  12. package/dist/cjs/plugins/componentEventListeners.js +1 -1
  13. package/dist/cjs/plugins/reactKeys.js +1 -1
  14. package/dist/esm/components/CustomNodeView.js +82 -6
  15. package/dist/esm/components/NodeView.js +14 -134
  16. package/dist/esm/components/OutputSpec.js +1 -1
  17. package/dist/esm/components/ReactNodeView.js +85 -0
  18. package/dist/esm/components/TextNodeView.js +1 -1
  19. package/dist/esm/findDOMNode.js +31 -0
  20. package/dist/esm/hooks/useEditor.js +14 -3
  21. package/dist/esm/hooks/useEditorEffect.js +5 -2
  22. package/dist/esm/hooks/useIsNodeSelected.js +11 -0
  23. package/dist/esm/index.js +1 -0
  24. package/dist/esm/plugins/componentEventListeners.js +1 -1
  25. package/dist/esm/plugins/reactKeys.js +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/dist/types/components/CustomNodeView.d.ts +3 -12
  28. package/dist/types/components/ReactNodeView.d.ts +11 -0
  29. package/dist/types/contexts/EditorContext.d.ts +2 -0
  30. package/dist/types/findDOMNode.d.ts +3 -0
  31. package/dist/types/hooks/useEditor.d.ts +1 -0
  32. package/dist/types/hooks/useIsNodeSelected.d.ts +1 -0
  33. package/dist/types/index.d.ts +1 -0
  34. package/package.json +17 -4
package/README.md CHANGED
@@ -48,7 +48,7 @@ yarn add @handlewithcare/react-prosemirror prosemirror-view@1.37.1 prosemirror-s
48
48
  - [`useEditorEventCallback`](#useeditoreventcallback)
49
49
  - [`useEditorEventListener`](#useeditoreventlistener)
50
50
  - [Building node views with React](#building-node-views-with-react)
51
- - [What's changing in v2?](#whats-changing-in-v2)
51
+ - [What's new in v2?](#whats-new-in-v2)
52
52
  - [API changes](#api-changes)
53
53
  - [API](#api)
54
54
  - [`ProseMirror`](#prosemirror)
@@ -60,7 +60,9 @@ yarn add @handlewithcare/react-prosemirror prosemirror-view@1.37.1 prosemirror-s
60
60
  - [`NodeViewComponentProps`](#nodeviewcomponentprops)
61
61
  - [`useStopEvent`](#usestopevent)
62
62
  - [`useSelectNode`](#useselectnode)
63
+ - [`useIsNodeSelected`](#useisnodeselected)
63
64
  - [`widget`](#widget)
65
+ - [Looking for someone to collaborate with?](#looking-for-someone-to-collaborate-with)
64
66
 
65
67
  <!-- tocstop -->
66
68
 
@@ -421,9 +423,9 @@ function ProseMirrorEditor() {
421
423
  }
422
424
  ```
423
425
 
424
- ## What's changing in v2?
426
+ ## What's new in v2?
425
427
 
426
- The upcoming v2 release constitutes a significant re-write of the library.
428
+ The v2 release constitutes a significant re-write of the library.
427
429
 
428
430
  Previously, React ProseMirror relied on ProseMirror's EditorView to manage the
429
431
  DOM for the editor. To integrate it with React, we used React
@@ -694,6 +696,16 @@ This hook can be used within a node view component to register
694
696
  The selectNode handler will only be called when a NodeSelection is created whose
695
697
  node is this one.
696
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
+
697
709
  ### `widget`
698
710
 
699
711
  ```tsx
@@ -708,3 +720,10 @@ type widget = (
708
720
 
709
721
  Like ProseMirror View's `Decoration.widget`, but with support for React
710
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 { contentDomRef, customNodeViewRef, customNodeViewRootRef, customNodeView, initialNode, node, getPos, initialOuterDeco, initialInnerDeco, innerDeco } = param;
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
- return /*#__PURE__*/ (0, _react.createElement)(node.isInline ? "span" : "div", {
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
+ });
@@ -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 _OutputSpec = require("./OutputSpec.js");
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
- (0, _react.useLayoutEffect)(()=>{
86
- if (!customNodeViewRef.current || !customNodeViewRootRef.current) return;
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
- getPos: getPos,
158
- innerDeco: innerDeco
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
- const decoratedElement = /*#__PURE__*/ (0, _react.cloneElement)(outerDeco.reduce(_ChildNodeViews.wrapInDeco, element), // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
- outerDeco.some((d)=>d.type.attrs.nodeName) ? {
178
- ref: domRef
179
- } : // we've already passed the domRef to the NodeView component
180
- // as a prop
181
- undefined);
182
- const childContextValue = (0, _react.useMemo)(()=>({
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("@nytimes/react-prosemirror only supports strings and arrays in toDOM");
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 _reactdom = require("react-dom");
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, _reactdom.findDOMNode)(this);
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.js");
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
- (0, _reactdom.flushSync)(()=>{
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
- return effect(view);
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
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "useIsNodeSelected", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return useIsNodeSelected;
9
+ }
10
+ });
11
+ const _react = require("react");
12
+ const _useSelectNode = require("./useSelectNode.js");
13
+ function useIsNodeSelected() {
14
+ const [isSelected, setIsSelected] = (0, _react.useState)(false);
15
+ (0, _useSelectNode.useSelectNode)(()=>{
16
+ setIsSelected(true);
17
+ }, ()=>{
18
+ setIsSelected(false);
19
+ });
20
+ return isSelected;
21
+ }
package/dist/cjs/index.js CHANGED
@@ -31,6 +31,9 @@ _export(exports, {
31
31
  useEditorState: function() {
32
32
  return _useEditorState.useEditorState;
33
33
  },
34
+ useIsNodeSelected: function() {
35
+ return _useIsNodeSelected.useIsNodeSelected;
36
+ },
34
37
  useSelectNode: function() {
35
38
  return _useSelectNode.useSelectNode;
36
39
  },
@@ -49,5 +52,6 @@ const _useEditorEventListener = require("./hooks/useEditorEventListener.js");
49
52
  const _useEditorState = require("./hooks/useEditorState.js");
50
53
  const _useStopEvent = require("./hooks/useStopEvent.js");
51
54
  const _useSelectNode = require("./hooks/useSelectNode.js");
55
+ const _useIsNodeSelected = require("./hooks/useIsNodeSelected.js");
52
56
  const _reactKeys = require("./plugins/reactKeys.js");
53
57
  const _ReactWidgetType = require("./decorations/ReactWidgetType.js");
@@ -26,7 +26,7 @@ function componentEventListeners(eventHandlerRegistry) {
26
26
  domEventHandlers[eventType] = handleEvent;
27
27
  }
28
28
  const plugin = new _prosemirrorstate.Plugin({
29
- key: new _prosemirrorstate.PluginKey("@nytimes/react-prosemirror/componentEventListeners"),
29
+ key: new _prosemirrorstate.PluginKey("@handlewithcare/react-prosemirror/componentEventListeners"),
30
30
  props: {
31
31
  handleDOMEvents: domEventHandlers
32
32
  }
@@ -24,7 +24,7 @@ function createNodeKey() {
24
24
  const key = Math.floor(Math.random() * 0xffffffffffff).toString(16);
25
25
  return key;
26
26
  }
27
- const reactKeysPluginKey = new _prosemirrorstate.PluginKey("@nytimes/react-prosemirror/reactKeys");
27
+ const reactKeysPluginKey = new _prosemirrorstate.PluginKey("@handlewithcare/react-prosemirror/reactKeys");
28
28
  function reactKeys() {
29
29
  let composing = false;
30
30
  return new _prosemirrorstate.Plugin({