@handlewithcare/react-prosemirror 2.9.0-tiptap.24 → 3.0.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.
Files changed (143) hide show
  1. package/README.md +140 -75
  2. package/dist/cjs/StaticEditorView.js +0 -3
  3. package/dist/cjs/components/ChildNodeViews.js +4 -4
  4. package/dist/cjs/components/NativeWidgetView.js +2 -2
  5. package/dist/cjs/components/OutputSpec.js +10 -3
  6. package/dist/cjs/components/ProseMirror.js +11 -17
  7. package/dist/cjs/components/SeparatorHackView.js +2 -2
  8. package/dist/cjs/components/TrailingHackView.js +2 -2
  9. package/dist/cjs/components/WidgetView.js +2 -2
  10. package/dist/cjs/components/marks/DefaultMarkView.js +2 -1
  11. package/dist/cjs/components/marks/MarkView.js +2 -2
  12. package/dist/cjs/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +16 -7
  13. package/dist/cjs/components/marks/ReactMarkView.js +26 -6
  14. package/dist/cjs/components/nodes/DefaultNodeView.js +3 -2
  15. package/dist/cjs/components/nodes/DocNodeView.js +7 -6
  16. package/dist/cjs/components/nodes/NodeView.js +17 -6
  17. package/dist/cjs/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +22 -9
  18. package/dist/cjs/components/nodes/ReactNodeView.js +59 -17
  19. package/dist/cjs/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +3 -3
  20. package/dist/cjs/hooks/useEditor.js +0 -4
  21. package/dist/cjs/hooks/useEditorEventCallback.js +1 -1
  22. package/dist/cjs/hooks/useMarkViewDescription.js +24 -21
  23. package/dist/cjs/hooks/useNodePos.js +18 -0
  24. package/dist/cjs/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +30 -25
  25. package/dist/cjs/index.js +8 -0
  26. package/dist/cjs/refs.js +28 -0
  27. package/dist/cjs/viewdesc.js +18 -5
  28. package/dist/esm/StaticEditorView.js +0 -3
  29. package/dist/esm/components/ChildNodeViews.js +4 -4
  30. package/dist/esm/components/NativeWidgetView.js +2 -2
  31. package/dist/esm/components/OutputSpec.js +10 -3
  32. package/dist/esm/components/ProseMirror.js +11 -17
  33. package/dist/esm/components/SeparatorHackView.js +2 -2
  34. package/dist/esm/components/TrailingHackView.js +2 -2
  35. package/dist/esm/components/WidgetView.js +2 -2
  36. package/dist/esm/components/marks/DefaultMarkView.js +2 -1
  37. package/dist/esm/components/marks/MarkView.js +2 -2
  38. package/dist/esm/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +14 -5
  39. package/dist/esm/components/marks/ReactMarkView.js +26 -6
  40. package/dist/esm/components/nodes/DefaultNodeView.js +3 -2
  41. package/dist/esm/components/nodes/DocNodeView.js +8 -7
  42. package/dist/esm/components/nodes/NodeView.js +7 -4
  43. package/dist/esm/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +20 -7
  44. package/dist/esm/components/nodes/ReactNodeView.js +59 -17
  45. package/dist/esm/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +1 -1
  46. package/dist/esm/hooks/useEditor.js +0 -4
  47. package/dist/esm/hooks/useEditorEffect.js +0 -4
  48. package/dist/esm/hooks/useEditorEventCallback.js +6 -4
  49. package/dist/esm/hooks/useMarkViewDescription.js +26 -23
  50. package/dist/esm/hooks/useNodePos.js +15 -0
  51. package/dist/esm/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +29 -24
  52. package/dist/esm/index.js +2 -0
  53. package/dist/esm/refs.js +18 -0
  54. package/dist/esm/viewdesc.js +13 -6
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/dist/types/AbstractEditorView.d.ts +0 -1
  57. package/dist/types/StaticEditorView.d.ts +0 -1
  58. package/dist/types/components/OutputSpec.d.ts +2 -1
  59. package/dist/types/components/ProseMirror.d.ts +3 -11
  60. package/dist/types/components/ProseMirrorDoc.d.ts +2 -2
  61. package/dist/types/components/marks/DefaultMarkView.d.ts +1 -1
  62. package/dist/types/components/marks/MarkViewComponentProps.d.ts +4 -3
  63. package/dist/types/components/marks/{CustomMarkView.d.ts → MarkViewConstructorView.d.ts} +1 -1
  64. package/dist/types/components/nodes/DefaultNodeView.d.ts +1 -1
  65. package/dist/types/components/nodes/DocNodeView.d.ts +2 -2
  66. package/dist/types/components/nodes/NodeView.d.ts +1 -0
  67. package/dist/types/components/nodes/NodeViewComponentProps.d.ts +4 -3
  68. package/dist/types/components/{CustomNodeView.d.ts → nodes/NodeViewConstructorView.d.ts} +1 -1
  69. package/dist/types/constants.d.ts +1 -1
  70. package/dist/types/contexts/{ChildDescriptorsContext.d.ts → ChildDescriptionsContext.d.ts} +1 -1
  71. package/dist/types/hooks/useEditorEffect.d.ts +0 -4
  72. package/dist/types/hooks/useEditorEventCallback.d.ts +6 -4
  73. package/dist/types/hooks/useMarkViewDescription.d.ts +6 -9
  74. package/dist/types/hooks/useNodePos.d.ts +9 -0
  75. package/dist/types/hooks/{useNodeViewDescriptor.d.ts → useNodeViewDescription.d.ts} +5 -9
  76. package/dist/types/index.d.ts +2 -0
  77. package/dist/types/props.d.ts +26 -26
  78. package/dist/types/refs.d.ts +2 -0
  79. package/dist/types/viewdesc.d.ts +4 -0
  80. package/package.json +12 -20
  81. package/dist/cjs/components/CustomNodeView.js +0 -132
  82. package/dist/cjs/components/DefaultNodeView.js +0 -67
  83. package/dist/cjs/components/DocNodeView.js +0 -96
  84. package/dist/cjs/components/MarkView.js +0 -119
  85. package/dist/cjs/components/NodeView.js +0 -86
  86. package/dist/cjs/components/NodeViewComponentProps.js +0 -4
  87. package/dist/cjs/components/ReactNodeView.js +0 -174
  88. package/dist/cjs/components/marks/OldMarkView.js +0 -120
  89. package/dist/cjs/tiptap/ReactProseMirrorNodeView.js +0 -26
  90. package/dist/cjs/tiptap/TiptapEditor.js +0 -34
  91. package/dist/cjs/tiptap/TiptapEditorContent.js +0 -142
  92. package/dist/cjs/tiptap/TiptapEditorView.js +0 -118
  93. package/dist/cjs/tiptap/TiptapNodeView.js +0 -26
  94. package/dist/cjs/tiptap/contexts/TiptapEditorContext.js +0 -12
  95. package/dist/cjs/tiptap/extensions/ReactProseMirror.js +0 -40
  96. package/dist/cjs/tiptap/hooks/useIsInReactProseMirror.js +0 -15
  97. package/dist/cjs/tiptap/hooks/useTiptapEditor.js +0 -43
  98. package/dist/cjs/tiptap/hooks/useTiptapEditorEffect.js +0 -35
  99. package/dist/cjs/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
  100. package/dist/cjs/tiptap/index.js +0 -48
  101. package/dist/cjs/tiptap/tiptapNodeView.js +0 -237
  102. package/dist/esm/components/CustomNodeView.js +0 -81
  103. package/dist/esm/components/DefaultNodeView.js +0 -16
  104. package/dist/esm/components/DocNodeView.js +0 -45
  105. package/dist/esm/components/MarkView.js +0 -68
  106. package/dist/esm/components/NodeView.js +0 -35
  107. package/dist/esm/components/NodeViewComponentProps.js +0 -1
  108. package/dist/esm/components/ReactNodeView.js +0 -123
  109. package/dist/esm/components/marks/OldMarkView.js +0 -69
  110. package/dist/esm/tiptap/ReactProseMirrorNodeView.js +0 -22
  111. package/dist/esm/tiptap/TiptapEditor.js +0 -24
  112. package/dist/esm/tiptap/TiptapEditorContent.js +0 -91
  113. package/dist/esm/tiptap/TiptapEditorView.js +0 -69
  114. package/dist/esm/tiptap/TiptapNodeView.js +0 -22
  115. package/dist/esm/tiptap/contexts/TiptapEditorContext.js +0 -2
  116. package/dist/esm/tiptap/extensions/ReactProseMirror.js +0 -30
  117. package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +0 -5
  118. package/dist/esm/tiptap/hooks/useTiptapEditor.js +0 -33
  119. package/dist/esm/tiptap/hooks/useTiptapEditorEffect.js +0 -42
  120. package/dist/esm/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
  121. package/dist/esm/tiptap/index.js +0 -9
  122. package/dist/esm/tiptap/tiptapNodeView.js +0 -205
  123. package/dist/types/components/DefaultNodeView.d.ts +0 -3
  124. package/dist/types/components/DocNodeView.d.ts +0 -12
  125. package/dist/types/components/MarkView.d.ts +0 -9
  126. package/dist/types/components/NodeView.d.ts +0 -11
  127. package/dist/types/components/NodeViewComponentProps.d.ts +0 -12
  128. package/dist/types/components/ReactNodeView.d.ts +0 -13
  129. package/dist/types/components/marks/OldMarkView.d.ts +0 -10
  130. package/dist/types/components/nodes/CustomNodeView.d.ts +0 -12
  131. package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +0 -15
  132. package/dist/types/tiptap/TiptapEditor.d.ts +0 -6
  133. package/dist/types/tiptap/TiptapEditorContent.d.ts +0 -19
  134. package/dist/types/tiptap/TiptapEditorView.d.ts +0 -16
  135. package/dist/types/tiptap/TiptapNodeView.d.ts +0 -15
  136. package/dist/types/tiptap/contexts/TiptapEditorContext.d.ts +0 -6
  137. package/dist/types/tiptap/extensions/ReactProseMirror.d.ts +0 -9
  138. package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +0 -1
  139. package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +0 -4
  140. package/dist/types/tiptap/hooks/useTiptapEditorEffect.d.ts +0 -21
  141. package/dist/types/tiptap/hooks/useTiptapEditorEventCallback.d.ts +0 -13
  142. package/dist/types/tiptap/index.d.ts +0 -9
  143. package/dist/types/tiptap/tiptapNodeView.d.ts +0 -50
@@ -1,6 +1,6 @@
1
- import React, { cloneElement, createElement, forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
2
- import { ChildDescriptorsContext } from "../../contexts/ChildDescriptorsContext.js";
3
- import { useNodeViewDescriptor } from "../../hooks/useNodeViewDescriptor.js";
1
+ import React, { createElement, forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
2
+ import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
3
+ import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
4
4
  import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
5
5
  export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function DocNodeView(param, ref) {
6
6
  let { as, node, getPos, decorations, innerDecorations, setMount, ...elementProps } = param;
@@ -11,14 +11,15 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
11
11
  node,
12
12
  getPos,
13
13
  decorations,
14
- innerDecorations
14
+ innerDecorations,
15
+ contentDOMRef: innerRef
15
16
  }), [
16
17
  node,
17
18
  getPos,
18
19
  decorations,
19
20
  innerDecorations
20
21
  ]);
21
- const { childContextValue } = useNodeViewDescriptor(innerRef, ()=>{
22
+ const { childContextValue } = useNodeViewDescription(()=>innerRef.current, ()=>innerRef.current, ()=>{
22
23
  const dom = innerRef.current;
23
24
  return {
24
25
  dom,
@@ -28,7 +29,7 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
28
29
  }
29
30
  };
30
31
  }, nodeProps);
31
- const children = /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
32
+ const children = /*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
32
33
  value: childContextValue
33
34
  }, /*#__PURE__*/ React.createElement(ChildNodeViews, {
34
35
  getPos: getPos,
@@ -40,6 +41,6 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
40
41
  suppressContentEditableWarning: true,
41
42
  ref: innerRef
42
43
  };
43
- const element = as ? /*#__PURE__*/ cloneElement(as, props, children) : /*#__PURE__*/ createElement("div", props, children);
44
+ const element = as ? /*#__PURE__*/ createElement(as, props, children) : /*#__PURE__*/ createElement("div", props, children);
44
45
  return nodeProps.decorations.reduce(wrapInDeco, element);
45
46
  }));
@@ -1,7 +1,7 @@
1
- import React, { memo, useContext, useMemo } from "react";
1
+ import React, { createContext, memo, useContext, useMemo } from "react";
2
2
  import { NodeViewContext } from "../../contexts/NodeViewContext.js";
3
- import { CustomNodeView } from "./CustomNodeView.js";
4
3
  import { DefaultNodeView } from "./DefaultNodeView.js";
4
+ import { NodeViewConstructorView } from "./NodeViewConstructorView.js";
5
5
  import { ReactNodeView } from "./ReactNodeView.js";
6
6
  export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
7
7
  const { components, constructors } = useContext(NodeViewContext);
@@ -14,7 +14,7 @@ export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
14
14
  const Component = useMemo(()=>{
15
15
  if (constructor) {
16
16
  return function NodeView(props) {
17
- return /*#__PURE__*/ React.createElement(CustomNodeView, {
17
+ return /*#__PURE__*/ React.createElement(NodeViewConstructorView, {
18
18
  constructor: constructor,
19
19
  ...props
20
20
  });
@@ -31,5 +31,8 @@ export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
31
31
  constructor,
32
32
  component
33
33
  ]);
34
- return /*#__PURE__*/ React.createElement(Component, props);
34
+ return /*#__PURE__*/ React.createElement(GetPosContext.Provider, {
35
+ value: props.getPos
36
+ }, /*#__PURE__*/ React.createElement(Component, props));
35
37
  });
38
+ export const GetPosContext = /*#__PURE__*/ createContext(null);
@@ -1,18 +1,23 @@
1
1
  import { DOMSerializer } from "prosemirror-model";
2
2
  import React, { cloneElement, memo, useMemo, useRef } from "react";
3
3
  import { createPortal } from "react-dom";
4
- import { ChildDescriptorsContext } from "../../contexts/ChildDescriptorsContext.js";
5
- import { useNodeViewDescriptor } from "../../hooks/useNodeViewDescriptor.js";
4
+ import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
5
+ import { useForceUpdate } from "../../hooks/useForceUpdate.js";
6
+ import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
6
7
  import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
7
- export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param) {
8
+ export const NodeViewConstructorView = /*#__PURE__*/ memo(function NodeViewConstructorView(param) {
8
9
  let { constructor, node, getPos, innerDeco, outerDeco } = param;
9
10
  const ref = useRef(null);
10
11
  const innerRef = useRef(null);
12
+ const forceUpdate = useForceUpdate();
11
13
  const nodeProps = useMemo(()=>({
12
14
  node,
13
15
  getPos,
14
16
  decorations: outerDeco,
15
- innerDecorations: innerDeco
17
+ innerDecorations: innerDeco,
18
+ contentDOMRef: {
19
+ current: null
20
+ }
16
21
  }), [
17
22
  node,
18
23
  getPos,
@@ -33,7 +38,7 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
33
38
  }
34
39
  return nodeView;
35
40
  };
36
- const { childContextValue, contentDOM } = useNodeViewDescriptor(ref, function() {
41
+ const { childContextValue, contentDOM } = useNodeViewDescription(()=>ref.current, (source)=>source?.contentDOM ?? null, function() {
37
42
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
38
43
  args[_key] = arguments[_key];
39
44
  }
@@ -50,14 +55,22 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
50
55
  nodeDOM.draggable = true;
51
56
  }
52
57
  }
58
+ if (contentDOM) {
59
+ // Force a re-render if we have a contentDOM,
60
+ // so that we properly create a portal into it
61
+ forceUpdate();
62
+ }
53
63
  return {
54
- ...nodeView,
55
64
  destroy () {
56
65
  if (nodeView.destroy) {
57
66
  nodeView.destroy();
58
67
  }
59
68
  wrapperDOM.removeChild(nodeDOM);
60
69
  },
70
+ dom: nodeView.dom,
71
+ contentDOM: nodeView.contentDOM,
72
+ multiType: nodeView.multiType,
73
+ update: nodeView.update?.bind(nodeView),
61
74
  selectNode: nodeView.selectNode?.bind(nodeView),
62
75
  deselectNode: nodeView.deselectNode?.bind(nodeView),
63
76
  stopEvent: nodeView.stopEvent?.bind(nodeView),
@@ -68,7 +81,7 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
68
81
  const props = {
69
82
  ref: innerRef
70
83
  };
71
- const children = !node.isLeaf && contentDOM ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
84
+ const children = !node.isLeaf && contentDOM ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
72
85
  value: childContextValue
73
86
  }, /*#__PURE__*/ React.createElement(ChildNodeViews, {
74
87
  getPos: getPos,
@@ -1,16 +1,19 @@
1
1
  import React, { cloneElement, memo, useCallback, useMemo, useRef, useState } from "react";
2
- import { ChildDescriptorsContext } from "../../contexts/ChildDescriptorsContext.js";
2
+ import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
3
3
  import { IgnoreMutationContext } from "../../contexts/IgnoreMutationContext.js";
4
4
  import { SelectNodeContext } from "../../contexts/SelectNodeContext.js";
5
5
  import { StopEventContext } from "../../contexts/StopEventContext.js";
6
- import { useNodeViewDescriptor } from "../../hooks/useNodeViewDescriptor.js";
6
+ import { useForceUpdate } from "../../hooks/useForceUpdate.js";
7
+ import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
7
8
  import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
8
9
  export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
9
10
  let { component: Component, outerDeco, getPos, node, innerDeco } = param;
10
11
  const [hasCustomSelectNode, setHasCustomSelectNode] = useState(false);
11
12
  const [selected, setSelected] = useState(false);
12
- const ref = useRef(null);
13
- const innerRef = useRef(null);
13
+ const forceUpdate = useForceUpdate();
14
+ const domRef = useRef(null);
15
+ const nodeDOMRef = useRef(null);
16
+ const contentDOMRef = useRef(null);
14
17
  const selectNodeRef = useRef(null);
15
18
  const deselectNodeRef = useRef(null);
16
19
  const stopEventRef = useRef(null);
@@ -40,7 +43,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
40
43
  };
41
44
  };
42
45
  }, []);
43
- const nodeProps = useMemo(()=>({
46
+ const nodeViewDescProps = useMemo(()=>({
44
47
  node: node,
45
48
  getPos: getPos,
46
49
  decorations: outerDeco,
@@ -51,10 +54,10 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
51
54
  node,
52
55
  outerDeco
53
56
  ]);
54
- const { childContextValue, contentDOM, nodeDOM } = useNodeViewDescriptor(ref, ()=>{
57
+ const { childContextValue, refUpdated } = useNodeViewDescription(()=>domRef.current, ()=>contentDOMRef.current, ()=>{
55
58
  setSelected(false);
56
59
  return {
57
- dom: innerRef.current ?? ref.current,
60
+ dom: nodeDOMRef.current ?? domRef.current,
58
61
  update () {
59
62
  return true;
60
63
  },
@@ -62,46 +65,85 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
62
65
  selectNode () {
63
66
  const selectNode = selectNodeRef.current;
64
67
  if (selectNode) {
65
- selectNode.call(this);
68
+ selectNode();
66
69
  }
67
70
  setSelected(true);
68
71
  },
69
72
  deselectNode () {
70
73
  const deselectNode = deselectNodeRef.current;
71
74
  if (deselectNode) {
72
- deselectNode.call(this);
75
+ deselectNode();
73
76
  }
74
77
  setSelected(false);
75
78
  },
76
79
  stopEvent (event) {
77
80
  const stopEvent = stopEventRef.current;
78
81
  if (stopEvent) {
79
- return stopEvent.call(this, event);
82
+ return stopEvent(event);
80
83
  }
81
84
  return false;
82
85
  },
83
86
  ignoreMutation (mutation) {
84
87
  const ignoreMutation = ignoreMutationRef.current;
85
88
  if (ignoreMutation) {
86
- return ignoreMutation.call(this, mutation);
89
+ return ignoreMutation(mutation);
87
90
  }
88
91
  return false;
89
92
  }
90
93
  };
91
- }, nodeProps);
94
+ }, nodeViewDescProps);
95
+ const setDOM = useCallback((el)=>{
96
+ domRef.current = el;
97
+ refUpdated();
98
+ }, [
99
+ refUpdated
100
+ ]);
101
+ const setNodeDOM = useCallback((el)=>{
102
+ if (!!nodeDOMRef.current !== !!el) {
103
+ // Force a re-render if the existence of nodeDOM
104
+ // is changing, since we use its existince to set
105
+ // some props
106
+ forceUpdate();
107
+ }
108
+ nodeDOMRef.current = el;
109
+ refUpdated();
110
+ }, [
111
+ forceUpdate,
112
+ refUpdated
113
+ ]);
114
+ const setContentDOM = useCallback((el)=>{
115
+ if (!!contentDOMRef.current !== !!el) {
116
+ // Force a re-render if the existence of contentDOM
117
+ // is changing, since we use its existince to set
118
+ // some props
119
+ forceUpdate();
120
+ }
121
+ contentDOMRef.current = el;
122
+ refUpdated();
123
+ }, [
124
+ forceUpdate,
125
+ refUpdated
126
+ ]);
127
+ const nodeProps = useMemo(()=>({
128
+ ...nodeViewDescProps,
129
+ contentDOMRef: setContentDOM
130
+ }), [
131
+ nodeViewDescProps,
132
+ setContentDOM
133
+ ]);
92
134
  const props = {
93
135
  nodeProps,
94
- ...!contentDOM && !nodeProps.node.isText && nodeDOM?.nodeName !== "BR" ? {
136
+ ...!contentDOMRef.current && !nodeProps.node.isText && nodeDOMRef.current?.nodeName !== "BR" ? {
95
137
  contentEditable: false,
96
138
  suppressContentEditableWarning: true
97
139
  } : null,
98
140
  ...!hasCustomSelectNode && selected ? {
99
141
  className: "ProseMirror-selectednode"
100
142
  } : null,
101
- ...!hasCustomSelectNode && selected || node.type.spec.draggable ? {
143
+ ...!hasCustomSelectNode && selected || !contentDOMRef.current && !nodeProps.node.isText && domRef.current?.nodeName !== "BR" && node.type.spec.draggable ? {
102
144
  draggable: true
103
145
  } : null,
104
- ref: innerRef
146
+ ref: setNodeDOM
105
147
  };
106
148
  const children = !node.isLeaf ? /*#__PURE__*/ React.createElement(ChildNodeViews, {
107
149
  getPos: getPos,
@@ -109,7 +151,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
109
151
  innerDecorations: innerDeco
110
152
  }) : null;
111
153
  const element = /*#__PURE__*/ cloneElement(outerDeco.reduce(wrapInDeco, /*#__PURE__*/ React.createElement(Component, props, children)), {
112
- ref
154
+ ref: setDOM
113
155
  });
114
156
  return /*#__PURE__*/ React.createElement(SelectNodeContext.Provider, {
115
157
  value: setSelectNode
@@ -117,7 +159,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
117
159
  value: setStopEvent
118
160
  }, /*#__PURE__*/ React.createElement(IgnoreMutationContext.Provider, {
119
161
  value: setIgnoreMutation
120
- }, /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
162
+ }, /*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
121
163
  value: childContextValue
122
164
  }, element))));
123
165
  });
@@ -1,5 +1,5 @@
1
1
  import { createContext } from "react";
2
- export const ChildDescriptorsContext = createContext({
2
+ export const ChildDescriptionsContext = createContext({
3
3
  parentRef: {
4
4
  current: undefined
5
5
  },
@@ -101,11 +101,7 @@ let didWarnValueDefaultValue = false;
101
101
  // running effects. Running effects will reattach selection
102
102
  // change listeners if the EditorView has been destroyed.
103
103
  if (view instanceof ReactEditorView && !view.isDestroyed) {
104
- // Plugins might dispatch transactions from their
105
- // view update lifecycle hooks
106
- flushSyncRef.current = false;
107
104
  view.commitPendingEffects();
108
- flushSyncRef.current = true;
109
105
  }
110
106
  });
111
107
  view.update(directEditorProps);
@@ -15,10 +15,6 @@ import { useLayoutGroupEffect } from "./useLayoutGroupEffect.js";
15
15
  * synchronously after all DOM mutations, but they do so
16
16
  * _after_ the EditorView has been updated, even when the
17
17
  * EditorView lives in an ancestor component.
18
- *
19
- * This hook can only be used in a component that is mounted
20
- * as a child of the TiptapEditorView component, including
21
- * React node view components.
22
18
  */ export function useEditorEffect(effect, dependencies) {
23
19
  const { view, flushSyncRef } = useContext(EditorContext);
24
20
  // The rules of hooks want `effect` to be included in the
@@ -15,9 +15,11 @@ function assertIsReactEditorView(view) {
15
15
  * The callback will be called with the EditorView instance
16
16
  * as its first argument.
17
17
  *
18
- * This hook can only be used in a component that is mounted
19
- * as a child of the TiptapEditorView component, including
20
- * React node view components.
18
+ * This hook is dependent on both the
19
+ * `EditorViewContext.Provider` and the
20
+ * `DeferredLayoutEffectProvider`. It can only be used in a
21
+ * component that is mounted as a child of both of these
22
+ * providers.
21
23
  */ export function useEditorEventCallback(callback) {
22
24
  const ref = useRef(callback);
23
25
  const { view } = useContext(EditorContext);
@@ -31,7 +33,7 @@ function assertIsReactEditorView(view) {
31
33
  args[_key] = arguments[_key];
32
34
  }
33
35
  assertIsReactEditorView(view);
34
- return ref.current.call(this, view, ...args);
36
+ return ref.current(view, ...args);
35
37
  }, [
36
38
  view
37
39
  ]);
@@ -1,25 +1,21 @@
1
- import { useContext, useMemo, useRef, useState } from "react";
1
+ import { useCallback, useContext, useMemo, useRef } from "react";
2
2
  import { ReactEditorView } from "../ReactEditorView.js";
3
- import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js";
4
4
  import { EditorContext } from "../contexts/EditorContext.js";
5
- import { MarkViewDesc, sortViewDescs } from "../viewdesc.js";
5
+ import { ReactMarkViewDesc, sortViewDescs } from "../viewdesc.js";
6
6
  import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
7
7
  import { useEffectEvent } from "./useEffectEvent.js";
8
- function findContentDOM(source, children, dom) {
9
- return source?.contentDOM ?? children[0]?.dom?.parentElement ?? dom;
10
- }
11
- export function useMarkViewDescription(ref, constructor, props) {
8
+ export function useMarkViewDescription(getDOM, getContentDOM, constructor, props) {
12
9
  const { view } = useContext(EditorContext);
13
- const { parentRef, siblingsRef } = useContext(ChildDescriptorsContext);
14
- const [dom, setDOM] = useState(null);
15
- const [contentDOM, setContentDOM] = useState(null);
10
+ const { parentRef, siblingsRef } = useContext(ChildDescriptionsContext);
11
+ const contentDOMRef = useRef(null);
16
12
  const viewDescRef = useRef();
17
13
  const childrenRef = useRef([]);
18
14
  const create = useEffectEvent(()=>{
19
15
  if (!(view instanceof ReactEditorView)) {
20
16
  return;
21
17
  }
22
- const dom = ref.current;
18
+ const dom = getDOM();
23
19
  if (!dom) {
24
20
  return;
25
21
  }
@@ -30,10 +26,9 @@ export function useMarkViewDescription(ref, constructor, props) {
30
26
  }
31
27
  const parent = parentRef.current;
32
28
  const children = childrenRef.current;
33
- const contentDOM = findContentDOM(markView, children, ref.current);
34
- const viewDesc = new MarkViewDesc(parent, children, getPos, mark, dom, contentDOM, markView);
35
- setDOM(dom);
36
- setContentDOM(contentDOM);
29
+ const contentDOM = getContentDOM(markView);
30
+ const viewDesc = new ReactMarkViewDesc(parent, children, getPos, mark, dom, contentDOM ?? markView.dom, markView);
31
+ contentDOMRef.current = contentDOM;
37
32
  return viewDesc;
38
33
  });
39
34
  const update = useEffectEvent(()=>{
@@ -44,12 +39,12 @@ export function useMarkViewDescription(ref, constructor, props) {
44
39
  if (!viewDesc) {
45
40
  return false;
46
41
  }
47
- const dom = ref.current;
42
+ const dom = getDOM();
48
43
  if (!dom || dom !== viewDesc.dom) {
49
44
  return false;
50
45
  }
51
- const contentDOM = findContentDOM(viewDesc, viewDesc.children, dom);
52
- if (contentDOM !== viewDesc.contentDOM) {
46
+ const contentDOM = getContentDOM(viewDesc);
47
+ if (contentDOM !== (viewDesc.contentDOM ?? dom)) {
53
48
  return false;
54
49
  }
55
50
  const { mark } = props;
@@ -66,8 +61,7 @@ export function useMarkViewDescription(ref, constructor, props) {
66
61
  const index = siblings.indexOf(viewDesc);
67
62
  siblings.splice(index, 1);
68
63
  }
69
- setDOM(null);
70
- setContentDOM(null);
64
+ contentDOMRef.current = null;
71
65
  });
72
66
  useClientLayoutEffect(()=>{
73
67
  viewDescRef.current = create();
@@ -78,6 +72,16 @@ export function useMarkViewDescription(ref, constructor, props) {
78
72
  create,
79
73
  destroy
80
74
  ]);
75
+ const refUpdated = useCallback(()=>{
76
+ if (!update()) {
77
+ destroy();
78
+ viewDescRef.current = create();
79
+ }
80
+ }, [
81
+ create,
82
+ destroy,
83
+ update
84
+ ]);
81
85
  useClientLayoutEffect(()=>{
82
86
  if (!update()) {
83
87
  destroy();
@@ -108,8 +112,7 @@ export function useMarkViewDescription(ref, constructor, props) {
108
112
  ]);
109
113
  return {
110
114
  childContextValue,
111
- dom,
112
- contentDOM,
113
- ref
115
+ contentDOM: contentDOMRef.current ?? viewDescRef.current?.dom,
116
+ refUpdated
114
117
  };
115
118
  }
@@ -0,0 +1,15 @@
1
+ import { useContext } from "react";
2
+ import { GetPosContext } from "../components/nodes/NodeView.js";
3
+ import { useEditorState } from "./useEditorState.js";
4
+ /**
5
+ * Get this node's current position in the document.
6
+ *
7
+ * Using this hook will subscribe this node to the
8
+ * EditorState, which means that it will be re-rendered
9
+ * on every EditorState update. This may have performance
10
+ * implications for large documents.
11
+ */ export function useNodePos() {
12
+ useEditorState();
13
+ const getPos = useContext(GetPosContext);
14
+ return getPos();
15
+ }
@@ -1,26 +1,21 @@
1
- import { useContext, useMemo, useRef, useState } from "react";
1
+ import { useCallback, useContext, useMemo, useRef } from "react";
2
2
  import { ReactEditorView } from "../ReactEditorView.js";
3
- import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js";
4
4
  import { EditorContext } from "../contexts/EditorContext.js";
5
5
  import { CompositionViewDesc, ReactNodeViewDesc, sortViewDescs } from "../viewdesc.js";
6
6
  import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
7
7
  import { useEffectEvent } from "./useEffectEvent.js";
8
- function findContentDOM(source, children) {
9
- return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
10
- }
11
- export function useNodeViewDescriptor(ref, constructor, props) {
8
+ export function useNodeViewDescription(getDOM, getContentDOM, constructor, props) {
12
9
  const { view } = useContext(EditorContext);
13
- const { parentRef, siblingsRef } = useContext(ChildDescriptorsContext);
14
- const [dom, setDOM] = useState(null);
15
- const [nodeDOM, setNodeDOM] = useState(null);
16
- const [contentDOM, setContentDOM] = useState(null);
10
+ const { parentRef, siblingsRef } = useContext(ChildDescriptionsContext);
11
+ const contentDOMRef = useRef(null);
17
12
  const viewDescRef = useRef();
18
13
  const childrenRef = useRef([]);
19
14
  const create = useEffectEvent(()=>{
20
15
  if (!(view instanceof ReactEditorView)) {
21
16
  return;
22
17
  }
23
- const dom = ref.current;
18
+ const dom = getDOM();
24
19
  if (!dom) {
25
20
  return;
26
21
  }
@@ -31,12 +26,15 @@ export function useNodeViewDescriptor(ref, constructor, props) {
31
26
  }
32
27
  const parent = parentRef.current;
33
28
  const children = childrenRef.current;
34
- const contentDOM = findContentDOM(nodeView, children);
29
+ const contentDOM = getContentDOM(nodeView);
35
30
  const nodeDOM = nodeView.dom;
36
31
  const viewDesc = new ReactNodeViewDesc(parent, children, getPos, node, decorations, innerDecorations, dom, contentDOM, nodeDOM, nodeView);
37
- setDOM(dom);
38
- setContentDOM(contentDOM);
39
- setNodeDOM(nodeDOM);
32
+ const siblings = siblingsRef.current;
33
+ if (!siblings.includes(viewDesc)) {
34
+ siblings.push(viewDesc);
35
+ }
36
+ siblings.sort(sortViewDescs);
37
+ contentDOMRef.current = getContentDOM(nodeView);
40
38
  return viewDesc;
41
39
  });
42
40
  const update = useEffectEvent(()=>{
@@ -47,11 +45,11 @@ export function useNodeViewDescriptor(ref, constructor, props) {
47
45
  if (!viewDesc) {
48
46
  return false;
49
47
  }
50
- const dom = ref.current;
48
+ const dom = getDOM();
51
49
  if (!dom || dom !== viewDesc.dom) {
52
50
  return false;
53
51
  }
54
- const contentDOM = findContentDOM(viewDesc, viewDesc.children);
52
+ const contentDOM = getContentDOM(viewDesc);
55
53
  if (contentDOM !== viewDesc.contentDOM) {
56
54
  return false;
57
55
  }
@@ -72,9 +70,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
72
70
  const index = siblings.indexOf(viewDesc);
73
71
  siblings.splice(index, 1);
74
72
  }
75
- setDOM(null);
76
- setContentDOM(null);
77
- setNodeDOM(null);
73
+ contentDOMRef.current = null;
78
74
  });
79
75
  useClientLayoutEffect(()=>{
80
76
  viewDescRef.current = create();
@@ -85,6 +81,17 @@ export function useNodeViewDescriptor(ref, constructor, props) {
85
81
  create,
86
82
  destroy
87
83
  ]);
84
+ const refUpdated = useCallback(()=>{
85
+ if (!viewDescRef.current) return;
86
+ if (!update()) {
87
+ destroy();
88
+ viewDescRef.current = create();
89
+ }
90
+ }, [
91
+ create,
92
+ destroy,
93
+ update
94
+ ]);
88
95
  useClientLayoutEffect(()=>{
89
96
  if (!update()) {
90
97
  destroy();
@@ -136,9 +143,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
136
143
  ]);
137
144
  return {
138
145
  childContextValue,
139
- dom,
140
- contentDOM,
141
- nodeDOM,
142
- ref
146
+ contentDOM: contentDOMRef.current,
147
+ refUpdated
143
148
  };
144
149
  }
package/dist/esm/index.js CHANGED
@@ -6,6 +6,7 @@ export { useEditorEffect } from "./hooks/useEditorEffect.js";
6
6
  export { useEditorEventCallback } from "./hooks/useEditorEventCallback.js";
7
7
  export { useEditorEventListener } from "./hooks/useEditorEventListener.js";
8
8
  export { useEditorState } from "./hooks/useEditorState.js";
9
+ export { useNodePos } from "./hooks/useNodePos.js";
9
10
  export { useStopEvent } from "./hooks/useStopEvent.js";
10
11
  export { useSelectNode } from "./hooks/useSelectNode.js";
11
12
  export { useIgnoreMutation } from "./hooks/useIgnoreMutation.js";
@@ -13,3 +14,4 @@ export { useIsEditorStatic } from "./hooks/useIsEditorStatic.js";
13
14
  export { useIsNodeSelected } from "./hooks/useIsNodeSelected.js";
14
15
  export { reactKeys } from "./plugins/reactKeys.js";
15
16
  export { widget } from "./decorations/ReactWidgetType.js";
17
+ export { useMergedDOMRefs } from "./refs.js";
@@ -0,0 +1,18 @@
1
+ import { useCallback } from "react";
2
+ export function useMergedDOMRefs() {
3
+ for(var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++){
4
+ refs[_key] = arguments[_key];
5
+ }
6
+ return useCallback((value)=>{
7
+ refs.forEach((ref)=>{
8
+ if (typeof ref === "function") {
9
+ ref(value);
10
+ return;
11
+ }
12
+ if (ref) {
13
+ ref.current = value;
14
+ }
15
+ });
16
+ // eslint-disable-next-line react-hooks/exhaustive-deps
17
+ }, refs);
18
+ }
@@ -711,25 +711,32 @@ let CustomNodeViewDesc = class CustomNodeViewDesc extends NodeViewDesc {
711
711
  }
712
712
  }
713
713
  selectNode() {
714
- this.spec.selectNode ? this.spec.selectNode.call(this) : super.selectNode();
714
+ this.spec.selectNode ? this.spec.selectNode() : super.selectNode();
715
715
  }
716
716
  deselectNode() {
717
- this.spec.deselectNode ? this.spec.deselectNode.call(this) : super.deselectNode();
717
+ this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
718
718
  }
719
719
  setSelection(anchor, head, view, force) {
720
- this.spec.setSelection ? this.spec.setSelection.call(this, anchor, head, view.root) : super.setSelection(anchor, head, view, force);
720
+ this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root) : super.setSelection(anchor, head, view, force);
721
721
  }
722
722
  destroy() {
723
723
  if (this.spec.destroy) this.spec.destroy();
724
724
  super.destroy();
725
725
  }
726
726
  stopEvent(event) {
727
- return this.spec.stopEvent ? this.spec.stopEvent.call(this, event) : false;
727
+ return this.spec.stopEvent ? this.spec.stopEvent(event) : false;
728
728
  }
729
729
  ignoreMutation(mutation) {
730
- return this.spec.ignoreMutation ? this.spec.ignoreMutation.call(this, mutation) : super.ignoreMutation(mutation);
730
+ return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
731
731
  }
732
732
  };
733
+ export class ReactMarkViewDesc extends MarkViewDesc {
734
+ destroy() {
735
+ // React has already destroyed the children (if needed).
736
+ this.children = [];
737
+ super.destroy();
738
+ }
739
+ }
733
740
  export class ReactNodeViewDesc extends CustomNodeViewDesc {
734
741
  updateChildren(_view, _pos) {
735
742
  // React has already updated the children.
@@ -744,7 +751,7 @@ export class ReactNodeViewDesc extends CustomNodeViewDesc {
744
751
  super.destroy();
745
752
  }
746
753
  }
747
- function sameOuterDeco(a, b) {
754
+ export function sameOuterDeco(a, b) {
748
755
  if (a.length != b.length) return false;
749
756
  // @ts-expect-error ...
750
757
  for(let i = 0; i < a.length; i++)if (!a[i].type.eq(b[i].type)) return false;