@handlewithcare/react-prosemirror 2.5.0 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/cjs/ReactEditorView.js +6 -6
  2. package/dist/cjs/components/ChildNodeViews.js +6 -6
  3. package/dist/cjs/components/CustomNodeView.js +77 -121
  4. package/dist/cjs/components/DefaultNodeView.js +67 -0
  5. package/dist/cjs/components/DocNodeView.js +33 -32
  6. package/dist/cjs/components/NodeView.js +31 -21
  7. package/dist/cjs/components/ProseMirror.js +20 -9
  8. package/dist/cjs/components/ProseMirrorDoc.js +7 -27
  9. package/dist/cjs/components/ReactNodeView.js +96 -58
  10. package/dist/cjs/hooks/useEditor.js +1 -1
  11. package/dist/cjs/hooks/useIgnoreMutation.js +1 -1
  12. package/dist/cjs/hooks/useNodeViewDescriptor.js +121 -78
  13. package/dist/cjs/hooks/useSelectNode.js +9 -7
  14. package/dist/cjs/hooks/useStopEvent.js +1 -1
  15. package/dist/cjs/plugins/beforeInputPlugin.js +12 -0
  16. package/dist/cjs/viewdesc.js +95 -17
  17. package/dist/esm/ReactEditorView.js +6 -6
  18. package/dist/esm/components/ChildNodeViews.js +6 -6
  19. package/dist/esm/components/CustomNodeView.js +78 -122
  20. package/dist/esm/components/DefaultNodeView.js +16 -0
  21. package/dist/esm/components/DocNodeView.js +33 -32
  22. package/dist/esm/components/NodeView.js +32 -22
  23. package/dist/esm/components/ProseMirror.js +20 -9
  24. package/dist/esm/components/ProseMirrorDoc.js +7 -28
  25. package/dist/esm/components/ReactNodeView.js +97 -59
  26. package/dist/esm/hooks/useEditor.js +1 -1
  27. package/dist/esm/hooks/useIgnoreMutation.js +1 -1
  28. package/dist/esm/hooks/useNodeViewDescriptor.js +123 -80
  29. package/dist/esm/hooks/useSelectNode.js +9 -7
  30. package/dist/esm/hooks/useStopEvent.js +1 -1
  31. package/dist/esm/plugins/beforeInputPlugin.js +12 -0
  32. package/dist/esm/viewdesc.js +92 -17
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/dist/types/ReactEditorView.d.ts +3 -2
  35. package/dist/types/components/CustomNodeView.d.ts +1 -1
  36. package/dist/types/components/DefaultNodeView.d.ts +3 -0
  37. package/dist/types/components/DocNodeView.d.ts +8 -13
  38. package/dist/types/components/NodeView.d.ts +4 -4
  39. package/dist/types/components/NodeViewComponentProps.d.ts +3 -4
  40. package/dist/types/components/ProseMirrorDoc.d.ts +14 -8
  41. package/dist/types/components/ReactNodeView.d.ts +3 -1
  42. package/dist/types/contexts/IgnoreMutationContext.d.ts +2 -1
  43. package/dist/types/contexts/NodeViewContext.d.ts +3 -1
  44. package/dist/types/contexts/SelectNodeContext.d.ts +3 -1
  45. package/dist/types/contexts/StopEventContext.d.ts +2 -1
  46. package/dist/types/hooks/useEditor.d.ts +1 -1
  47. package/dist/types/hooks/useNodeViewDescriptor.d.ts +18 -10
  48. package/dist/types/hooks/useSelectNode.d.ts +2 -1
  49. package/dist/types/viewdesc.d.ts +25 -8
  50. package/package.json +3 -3
  51. package/dist/cjs/hooks/useClientOnly.js +0 -19
  52. package/dist/esm/hooks/useClientOnly.js +0 -9
  53. package/dist/types/hooks/useClientOnly.d.ts +0 -1
@@ -11,12 +11,10 @@ Object.defineProperty(exports, "ReactNodeView", {
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
13
13
  const _IgnoreMutationContext = require("../contexts/IgnoreMutationContext.js");
14
- const _NodeViewContext = require("../contexts/NodeViewContext.js");
15
14
  const _SelectNodeContext = require("../contexts/SelectNodeContext.js");
16
15
  const _StopEventContext = require("../contexts/StopEventContext.js");
17
16
  const _useNodeViewDescriptor = require("../hooks/useNodeViewDescriptor.js");
18
17
  const _ChildNodeViews = require("./ChildNodeViews.js");
19
- const _OutputSpec = require("./OutputSpec.js");
20
18
  function _getRequireWildcardCache(nodeInterop) {
21
19
  if (typeof WeakMap !== "function") return null;
22
20
  var cacheBabelInterop = new WeakMap();
@@ -59,23 +57,40 @@ function _interop_require_wildcard(obj, nodeInterop) {
59
57
  return newObj;
60
58
  }
61
59
  const ReactNodeView = /*#__PURE__*/ (0, _react.memo)(function ReactNodeView(param) {
62
- let { outerDeco, getPos, node, innerDeco, ...props } = param;
63
- const domRef = (0, _react.useRef)(null);
64
- const nodeDomRef = (0, _react.useRef)(null);
65
- const contentDomRef = (0, _react.useRef)(null);
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, setIgnoreMutation, nodeViewDescRef } = (0, _useNodeViewDescriptor.useNodeViewDescriptor)(node, getPos, domRef, nodeDomRef, innerDeco, outerDeco, contentDomRef);
73
- const finalProps = {
74
- ...props,
75
- ...!hasContentDOM && nodeDomRef.current?.tagName !== "BR" && {
76
- contentEditable: false
77
- }
78
- };
60
+ let { component: Component, outerDeco, getPos, node, innerDeco } = param;
61
+ const [controlSelected, setControlSelected] = (0, _react.useState)(false);
62
+ const [selected, setSelected] = (0, _react.useState)(false);
63
+ const ref = (0, _react.useRef)(null);
64
+ const innerRef = (0, _react.useRef)(null);
65
+ const selectNodeRef = (0, _react.useRef)(null);
66
+ const deselectNodeRef = (0, _react.useRef)(null);
67
+ const stopEventRef = (0, _react.useRef)(null);
68
+ const ignoreMutationRef = (0, _react.useRef)(null);
69
+ const setSelectNode = (0, _react.useCallback)((selectHandler, deselectHandler)=>{
70
+ selectNodeRef.current = selectHandler;
71
+ deselectNodeRef.current = deselectHandler;
72
+ setControlSelected(true);
73
+ return ()=>{
74
+ selectNodeRef.current = null;
75
+ deselectNodeRef.current = null;
76
+ setControlSelected(false);
77
+ };
78
+ }, []);
79
+ const setStopEvent = (0, _react.useCallback)((handler)=>{
80
+ stopEventRef.current = handler;
81
+ return ()=>{
82
+ stopEventRef.current = null;
83
+ };
84
+ }, []);
85
+ const setIgnoreMutation = (0, _react.useCallback)((handler)=>{
86
+ ignoreMutationRef.current = handler;
87
+ return ()=>{
88
+ ignoreMutationRef.current = null;
89
+ return ()=>{
90
+ ignoreMutationRef.current = null;
91
+ };
92
+ };
93
+ }, []);
79
94
  const nodeProps = (0, _react.useMemo)(()=>({
80
95
  node: node,
81
96
  getPos: getPos,
@@ -87,45 +102,68 @@ const ReactNodeView = /*#__PURE__*/ (0, _react.memo)(function ReactNodeView(para
87
102
  node,
88
103
  outerDeco
89
104
  ]);
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
- ]);
105
+ const { childContextValue, contentDOM, nodeDOM } = (0, _useNodeViewDescriptor.useNodeViewDescriptor)(ref, ()=>{
106
+ setSelected(false);
107
+ return {
108
+ dom: innerRef.current ?? ref.current,
109
+ update () {
110
+ return true;
111
+ },
112
+ multiType: true,
113
+ selectNode () {
114
+ const selectNode = selectNodeRef.current;
115
+ if (selectNode) {
116
+ selectNode();
117
+ }
118
+ setSelected(true);
119
+ },
120
+ deselectNode () {
121
+ const deselectNode = deselectNodeRef.current;
122
+ if (deselectNode) {
123
+ deselectNode();
124
+ }
125
+ setSelected(false);
126
+ },
127
+ stopEvent (event) {
128
+ const stopEvent = stopEventRef.current;
129
+ if (stopEvent) {
130
+ return stopEvent(event);
131
+ }
132
+ return false;
133
+ },
134
+ ignoreMutation (mutation) {
135
+ const ignoreMutation = ignoreMutationRef.current;
136
+ if (ignoreMutation) {
137
+ return ignoreMutation(mutation);
138
+ }
139
+ return false;
140
+ }
141
+ };
142
+ }, nodeProps);
143
+ const children = !node.isLeaf ? /*#__PURE__*/ _react.default.createElement(_ChildNodeViews.ChildNodeViews, {
144
+ getPos: getPos,
145
+ node: node,
146
+ innerDecorations: innerDeco
147
+ }) : null;
148
+ const innerProps = {
149
+ nodeProps,
150
+ ...!contentDOM && !nodeProps.node.isText && nodeDOM?.nodeName !== "BR" ? {
151
+ contentEditable: false,
152
+ suppressContentEditableWarning: true
153
+ } : null,
154
+ ...controlSelected && selected ? {
155
+ className: "ProseMirror-selectednode"
156
+ } : null,
157
+ ref: innerRef
158
+ };
159
+ const innerElement = /*#__PURE__*/ _react.default.createElement(Component, innerProps, children);
160
+ const props = {
161
+ ...controlSelected && selected || node.type.spec.draggable ? {
162
+ draggable: true
163
+ } : null,
164
+ ref
165
+ };
166
+ const decoratedElement = /*#__PURE__*/ (0, _react.cloneElement)(outerDeco.reduce(_ChildNodeViews.wrapInDeco, innerElement), props);
129
167
  return /*#__PURE__*/ _react.default.createElement(_SelectNodeContext.SelectNodeContext.Provider, {
130
168
  value: setSelectNode
131
169
  }, /*#__PURE__*/ _react.default.createElement(_StopEventContext.StopEventContext.Provider, {
@@ -21,7 +21,7 @@ let didWarnValueDefaultValue = false;
21
21
  function useEditor(mount, options) {
22
22
  if (process.env.NODE_ENV !== "production") {
23
23
  if (options.defaultState !== undefined && options.state !== undefined && !didWarnValueDefaultValue) {
24
- console.error("A component contains a ProseMirror editor with both value and defaultValue props. " + "ProseMirror editors must be either controlled or uncontrolled " + "(specify either the state prop, or the defaultState prop, but not both). " + "Decide between using a controlled or uncontrolled ProseMirror editor " + "and remove one of these props. More info: " + "https://reactjs.org/link/controlled-components");
24
+ console.error("A component contains a ProseMirror editor with both state and defaultState props. " + "ProseMirror editors must be either controlled or uncontrolled " + "(specify either the state prop, or the defaultState prop, but not both). " + "Decide between using a controlled or uncontrolled ProseMirror editor " + "and remove one of these props. More info: " + "https://reactjs.org/link/controlled-components");
25
25
  didWarnValueDefaultValue = true;
26
26
  }
27
27
  }
@@ -16,7 +16,7 @@ function useIgnoreMutation(ignoreMutation) {
16
16
  const register = (0, _react.useContext)(_IgnoreMutationContext.IgnoreMutationContext);
17
17
  const ignoreMutationMemo = (0, _useEditorEventCallback.useEditorEventCallback)(ignoreMutation);
18
18
  (0, _useEditorEffect.useEditorEffect)(()=>{
19
- register(ignoreMutationMemo);
19
+ return register(ignoreMutationMemo);
20
20
  }, [
21
21
  register,
22
22
  ignoreMutationMemo
@@ -9,111 +9,154 @@ Object.defineProperty(exports, "useNodeViewDescriptor", {
9
9
  }
10
10
  });
11
11
  const _react = require("react");
12
+ const _ReactEditorView = require("../ReactEditorView.js");
12
13
  const _ChildDescriptorsContext = require("../contexts/ChildDescriptorsContext.js");
13
14
  const _EditorContext = require("../contexts/EditorContext.js");
14
15
  const _viewdesc = require("../viewdesc.js");
15
16
  const _useClientLayoutEffect = require("./useClientLayoutEffect.js");
16
- function useNodeViewDescriptor(node, getPos, domRef, nodeDomRef, innerDecorations, outerDecorations, contentDOMRef) {
17
+ function findContentDOM(source, children) {
18
+ return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
19
+ }
20
+ function useNodeViewDescriptor(ref, constructor, props) {
17
21
  const { view } = (0, _react.useContext)(_EditorContext.EditorContext);
18
- const [hasContentDOM, setHasContentDOM] = (0, _react.useState)(true);
19
- const nodeViewDescRef = (0, _react.useRef)();
20
- const stopEvent = (0, _react.useRef)(()=>false);
21
- const setStopEvent = (0, _react.useCallback)((newStopEvent)=>{
22
- stopEvent.current = newStopEvent;
23
- }, []);
24
- const ignoreMutation = (0, _react.useRef)(()=>false);
25
- const setIgnoreMutation = (0, _react.useCallback)((newIgnoreMutation)=>{
26
- ignoreMutation.current = newIgnoreMutation;
27
- }, []);
28
- const selectNode = (0, _react.useRef)(()=>{
29
- if (!nodeDomRef.current) return;
30
- if (nodeDomRef.current.nodeType == 1) nodeDomRef.current.classList.add("ProseMirror-selectednode");
31
- if (contentDOMRef?.current || !node.type.spec.draggable) (domRef?.current ?? nodeDomRef.current).draggable = true;
32
- });
33
- const deselectNode = (0, _react.useRef)(()=>{
34
- if (!nodeDomRef.current) return;
35
- if (nodeDomRef.current.nodeType == 1) {
36
- nodeDomRef.current.classList.remove("ProseMirror-selectednode");
37
- if (contentDOMRef?.current || !node.type.spec.draggable) (domRef?.current ?? nodeDomRef.current).removeAttribute("draggable");
22
+ const { parentRef, siblingsRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
23
+ const [dom, setDOM] = (0, _react.useState)(null);
24
+ const [nodeDOM, setNodeDOM] = (0, _react.useState)(null);
25
+ const [contentDOM, setContentDOM] = (0, _react.useState)(null);
26
+ const viewDescRef = (0, _react.useRef)();
27
+ const childrenRef = (0, _react.useRef)([]);
28
+ const create = (0, _react.useCallback)((props)=>{
29
+ if (!(view instanceof _ReactEditorView.ReactEditorView)) {
30
+ return;
38
31
  }
39
- });
40
- const setSelectNode = (0, _react.useCallback)((newSelectNode, newDeselectNode)=>{
41
- selectNode.current = newSelectNode;
42
- deselectNode.current = newDeselectNode;
43
- }, []);
44
- const { siblingsRef, parentRef } = (0, _react.useContext)(_ChildDescriptorsContext.ChildDescriptorsContext);
45
- const childDescriptors = (0, _react.useRef)([]);
46
- (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
32
+ const dom = ref.current;
33
+ if (!dom) {
34
+ return;
35
+ }
36
+ const { node, getPos, decorations, innerDecorations } = props;
37
+ const nodeView = constructor(node, view, getPos, decorations, innerDecorations);
38
+ if (!nodeView) {
39
+ return;
40
+ }
41
+ const parent = parentRef.current;
42
+ const children = childrenRef.current;
43
+ const contentDOM = findContentDOM(nodeView, children);
44
+ const nodeDOM = nodeView.dom;
45
+ const viewDesc = new _viewdesc.ReactNodeViewDesc(parent, children, getPos, node, decorations, innerDecorations, dom, contentDOM, nodeDOM, nodeView);
46
+ setDOM(dom);
47
+ setContentDOM(contentDOM);
48
+ setNodeDOM(nodeDOM);
49
+ return viewDesc;
50
+ }, [
51
+ ref,
52
+ parentRef,
53
+ constructor,
54
+ view
55
+ ]);
56
+ const update = (0, _react.useCallback)((props)=>{
57
+ if (!(view instanceof _ReactEditorView.ReactEditorView)) {
58
+ return false;
59
+ }
60
+ const viewDesc = viewDescRef.current;
61
+ if (!viewDesc) {
62
+ return false;
63
+ }
64
+ const dom = ref.current;
65
+ if (!dom || dom !== viewDesc.dom) {
66
+ return false;
67
+ }
68
+ const contentDOM = findContentDOM(viewDesc, viewDesc.children);
69
+ if (contentDOM !== viewDesc.contentDOM) {
70
+ return false;
71
+ }
72
+ if (!dom.contains(viewDesc.nodeDOM)) {
73
+ return false;
74
+ }
75
+ const { node, decorations, innerDecorations } = props;
76
+ return viewDesc.matchesNode(node, decorations, innerDecorations) || viewDesc.update(node, decorations, innerDecorations, view);
77
+ }, [
78
+ ref,
79
+ view
80
+ ]);
81
+ const destroy = (0, _react.useCallback)(()=>{
82
+ const viewDesc = viewDescRef.current;
83
+ if (!viewDesc) {
84
+ return;
85
+ }
86
+ viewDesc.destroy();
47
87
  const siblings = siblingsRef.current;
48
- return ()=>{
49
- if (!nodeViewDescRef.current) return;
50
- if (siblings.includes(nodeViewDescRef.current)) {
51
- const index = siblings.indexOf(nodeViewDescRef.current);
52
- siblings.splice(index, 1);
53
- }
54
- };
88
+ if (siblings.includes(viewDesc)) {
89
+ const index = siblings.indexOf(viewDesc);
90
+ siblings.splice(index, 1);
91
+ }
92
+ setDOM(null);
93
+ setContentDOM(null);
94
+ setNodeDOM(null);
55
95
  }, [
56
96
  siblingsRef
57
97
  ]);
58
- // eslint-disable-next-line react-hooks/exhaustive-deps
59
98
  (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
60
- if (!nodeDomRef.current) return;
61
- const firstChildDesc = childDescriptors.current[0];
62
- if (!nodeViewDescRef.current) {
63
- nodeViewDescRef.current = new _viewdesc.NodeViewDesc(parentRef.current, childDescriptors.current, getPos, node, outerDecorations, innerDecorations, domRef?.current ?? nodeDomRef.current, contentDOMRef?.current ?? firstChildDesc?.dom.parentElement ?? null, nodeDomRef.current, (event)=>!!stopEvent.current(event), ()=>selectNode.current(), ()=>deselectNode.current(), (mutation)=>ignoreMutation.current(mutation));
64
- } else {
65
- nodeViewDescRef.current.parent = parentRef.current;
66
- nodeViewDescRef.current.children = childDescriptors.current;
67
- nodeViewDescRef.current.node = node;
68
- nodeViewDescRef.current.outerDeco = outerDecorations;
69
- nodeViewDescRef.current.innerDeco = innerDecorations;
70
- nodeViewDescRef.current.dom = domRef?.current ?? nodeDomRef.current;
71
- nodeViewDescRef.current.dom.pmViewDesc = nodeViewDescRef.current;
72
- nodeViewDescRef.current.contentDOM = // If there's already a contentDOM, we can just
73
- // keep it; it won't have changed. This is especially
74
- // important during compositions, where the
75
- // firstChildDesc might not have a correct dom node set yet.
76
- contentDOMRef?.current ?? nodeViewDescRef.current.contentDOM ?? firstChildDesc?.dom.parentElement ?? null;
77
- nodeViewDescRef.current.nodeDOM = nodeDomRef.current;
99
+ if (!update(props)) {
100
+ destroy();
101
+ viewDescRef.current = create(props);
102
+ }
103
+ const viewDesc = viewDescRef.current;
104
+ if (!viewDesc) {
105
+ return;
78
106
  }
79
- setHasContentDOM(nodeViewDescRef.current.contentDOM !== null);
80
- if (!siblingsRef.current.includes(nodeViewDescRef.current)) {
81
- siblingsRef.current.push(nodeViewDescRef.current);
107
+ if (view.dom === viewDesc.dom && view instanceof _ReactEditorView.ReactEditorView) {
108
+ view.docView = viewDesc;
109
+ }
110
+ const parent = parentRef.current;
111
+ const siblings = siblingsRef.current;
112
+ const children = childrenRef.current;
113
+ viewDesc.parent = parent;
114
+ if (!siblings.includes(viewDesc)) {
115
+ siblings.push(viewDesc);
82
116
  }
83
- siblingsRef.current.sort(_viewdesc.sortViewDescs);
84
- for (const childDesc of childDescriptors.current){
85
- childDesc.parent = nodeViewDescRef.current;
117
+ siblings.sort(_viewdesc.sortViewDescs);
118
+ for (const child of children){
119
+ child.parent = viewDesc;
86
120
  // Because TextNodeViews can't locate the DOM nodes
87
121
  // for compositions, we need to override them here
88
- if (childDesc instanceof _viewdesc.CompositionViewDesc) {
89
- const compositionTopDOM = nodeViewDescRef.current.contentDOM?.firstChild;
122
+ if (child instanceof _viewdesc.CompositionViewDesc) {
123
+ const compositionTopDOM = viewDesc?.contentDOM?.firstChild;
90
124
  if (!compositionTopDOM) throw new Error(`Started a composition but couldn't find the text node it belongs to.`);
91
125
  let textDOM = compositionTopDOM;
92
126
  while(textDOM.firstChild){
93
127
  textDOM = textDOM.firstChild;
94
128
  }
95
129
  if (!textDOM || !(textDOM instanceof Text)) throw new Error(`Started a composition but couldn't find the text node it belongs to.`);
96
- childDesc.dom = compositionTopDOM;
97
- childDesc.textDOM = textDOM;
98
- childDesc.text = textDOM.data;
99
- childDesc.textDOM.pmViewDesc = childDesc;
130
+ child.dom = compositionTopDOM;
131
+ child.textDOM = textDOM;
132
+ child.text = textDOM.data;
133
+ child.textDOM.pmViewDesc = child;
100
134
  // It should not be possible to be in a composition because one could
101
135
  // not start between the renders that switch the view type.
102
- view.input.compositionNodes.push(childDesc);
136
+ view.input.compositionNodes.push(child);
103
137
  }
104
138
  }
139
+ });
140
+ (0, _useClientLayoutEffect.useClientLayoutEffect)(()=>{
105
141
  return ()=>{
106
- if (nodeViewDescRef.current?.children[0] instanceof _viewdesc.CompositionViewDesc && !view.composing) {
107
- nodeViewDescRef.current?.children[0].dom.parentNode?.removeChild(nodeViewDescRef.current?.children[0].dom);
108
- }
142
+ destroy();
143
+ viewDescRef.current = undefined;
109
144
  };
110
- });
145
+ }, [
146
+ destroy
147
+ ]);
148
+ const childContextValue = (0, _react.useMemo)(()=>({
149
+ parentRef: viewDescRef,
150
+ siblingsRef: childrenRef
151
+ }), [
152
+ childrenRef,
153
+ viewDescRef
154
+ ]);
111
155
  return {
112
- hasContentDOM,
113
- childDescriptors,
114
- nodeViewDescRef,
115
- setStopEvent,
116
- setSelectNode,
117
- setIgnoreMutation
156
+ childContextValue,
157
+ dom,
158
+ contentDOM,
159
+ nodeDOM,
160
+ ref
118
161
  };
119
162
  }
@@ -12,17 +12,19 @@ const _react = require("react");
12
12
  const _SelectNodeContext = require("../contexts/SelectNodeContext.js");
13
13
  const _useEditorEffect = require("./useEditorEffect.js");
14
14
  const _useEditorEventCallback = require("./useEditorEventCallback.js");
15
- function useSelectNode(selectNode, deselectNode) {
15
+ function noop() {
16
+ // empty
17
+ }
18
+ function useSelectNode(selectNode) {
19
+ let deselectNode = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : noop;
16
20
  const register = (0, _react.useContext)(_SelectNodeContext.SelectNodeContext);
17
21
  const selectNodeMemo = (0, _useEditorEventCallback.useEditorEventCallback)(selectNode);
18
- const deselectNodeMemo = (0, _useEditorEventCallback.useEditorEventCallback)(deselectNode ?? (()=>{
19
- // empty
20
- }));
22
+ const deselectNodeMemo = (0, _useEditorEventCallback.useEditorEventCallback)(deselectNode);
21
23
  return (0, _useEditorEffect.useEditorEffect)(()=>{
22
- register(selectNodeMemo, deselectNodeMemo);
24
+ return register(selectNodeMemo, deselectNodeMemo);
23
25
  }, [
24
- deselectNodeMemo,
25
26
  register,
26
- selectNodeMemo
27
+ selectNodeMemo,
28
+ deselectNodeMemo
27
29
  ]);
28
30
  }
@@ -16,7 +16,7 @@ function useStopEvent(stopEvent) {
16
16
  const register = (0, _react.useContext)(_StopEventContext.StopEventContext);
17
17
  const stopEventMemo = (0, _useEditorEventCallback.useEditorEventCallback)(stopEvent);
18
18
  (0, _useEditorEffect.useEditorEffect)(()=>{
19
- register(stopEventMemo);
19
+ return register(stopEventMemo);
20
20
  }, [
21
21
  register,
22
22
  stopEventMemo
@@ -96,6 +96,14 @@ function beforeInputPlugin(setCursorWrapper) {
96
96
  case "insertParagraph":
97
97
  case "insertLineBreak":
98
98
  {
99
+ // ProseMirror-view has a hack that runs the Enter event handlers
100
+ // on iOS, to avoid a bug in Safari with calling event.preventDefault() on
101
+ // Enter events.
102
+ //
103
+ // We want to prevent that hack, because we run the Enter event handlers
104
+ // here, where there is no such bug. So we set this flag, which prosemirror-view
105
+ // uses to check whether it should run the deferred event handlers.
106
+ view.input.lastIOSEnter = 0;
99
107
  // Fire a synthetic keydown event to trigger ProseMirror's keymap
100
108
  const keyEvent = new KeyboardEvent("keydown", {
101
109
  bubbles: true,
@@ -129,8 +137,12 @@ function beforeInputPlugin(setCursorWrapper) {
129
137
  break;
130
138
  }
131
139
  case "deleteWordBackward":
140
+ case "deleteHardLineBackward":
141
+ case "deleteSoftLineBackward":
132
142
  case "deleteContentBackward":
133
143
  case "deleteWordForward":
144
+ case "deleteHardLineForward":
145
+ case "deleteSoftLineForward":
134
146
  case "deleteContentForward":
135
147
  case "deleteContent":
136
148
  {
@@ -18,6 +18,9 @@ _export(exports, {
18
18
  NodeViewDesc: function() {
19
19
  return NodeViewDesc;
20
20
  },
21
+ ReactNodeViewDesc: function() {
22
+ return ReactNodeViewDesc;
23
+ },
21
24
  TextViewDesc: function() {
22
25
  return TextViewDesc;
23
26
  },
@@ -104,7 +107,9 @@ let ViewDesc = class ViewDesc {
104
107
  return 0;
105
108
  }
106
109
  destroy() {
107
- // pass
110
+ this.parent = undefined;
111
+ if (this.dom.pmViewDesc == this) this.dom.pmViewDesc = undefined;
112
+ for(let i = 0; i < this.children.length; i++)this.children[i].destroy();
108
113
  }
109
114
  posBeforeChild(child) {
110
115
  for(let i = 0, pos = this.posAtStart;; i++){
@@ -553,15 +558,8 @@ let NodeViewDesc = class NodeViewDesc extends ViewDesc {
553
558
  outerDeco;
554
559
  innerDeco;
555
560
  nodeDOM;
556
- stopEvent;
557
- selectNode;
558
- deselectNode;
559
- ignoreMutation;
560
- constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, stopEvent, selectNode, deselectNode, ignoreMutation){
561
- super(parent, children, getPos, dom, contentDOM), this.node = node, this.outerDeco = outerDeco, this.innerDeco = innerDeco, this.nodeDOM = nodeDOM, this.stopEvent = stopEvent, this.selectNode = selectNode, this.deselectNode = deselectNode, this.ignoreMutation = ignoreMutation;
562
- }
563
- updateOuterDeco() {
564
- // pass
561
+ constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM){
562
+ super(parent, children, getPos, dom, contentDOM), this.node = node, this.outerDeco = outerDeco, this.innerDeco = innerDeco, this.nodeDOM = nodeDOM;
565
563
  }
566
564
  parseRule() {
567
565
  // Experimental kludge to allow opt-in re-parsing of nodes
@@ -605,23 +603,46 @@ let NodeViewDesc = class NodeViewDesc extends ViewDesc {
605
603
  get border() {
606
604
  return this.node.isLeaf ? 0 : 1;
607
605
  }
606
+ updateChildren(_view, _pos) {
607
+ // Omitted to avoid reproducing lots of unused code.
608
+ // Overidden elsewhere in case this is ever vendored.
609
+ }
608
610
  // If this desc must be updated to match the given node decoration,
609
611
  // do so and return true.
610
- update(_node, _outerDeco, _innerDeco, _view) {
611
- this.dirty = NOT_DIRTY;
612
+ update(node, outerDeco, innerDeco, view) {
613
+ if (this.dirty == NODE_DIRTY || !node.sameMarkup(this.node)) return false;
614
+ this.updateInner(node, outerDeco, innerDeco, view);
612
615
  return true;
613
616
  }
617
+ updateInner(node, outerDeco, innerDeco, view) {
618
+ this.updateOuterDeco(outerDeco);
619
+ this.node = node;
620
+ this.innerDeco = innerDeco;
621
+ if (this.contentDOM) this.updateChildren(view, this.posAtStart);
622
+ this.dirty = NOT_DIRTY;
623
+ }
624
+ updateOuterDeco(outerDeco) {
625
+ this.outerDeco = outerDeco;
626
+ }
627
+ // Mark this node as being the selected node.
628
+ selectNode() {
629
+ if (this.nodeDOM.nodeType == 1) this.nodeDOM.classList.add("ProseMirror-selectednode");
630
+ if (this.contentDOM || !this.node.type.spec.draggable) this.dom.draggable = true;
631
+ }
632
+ // Remove selected node marking from this node.
633
+ deselectNode() {
634
+ if (this.nodeDOM.nodeType == 1) {
635
+ this.nodeDOM.classList.remove("ProseMirror-selectednode");
636
+ if (this.contentDOM || !this.node.type.spec.draggable) this.dom.removeAttribute("draggable");
637
+ }
638
+ }
614
639
  get domAtom() {
615
640
  return this.node.isAtom;
616
641
  }
617
642
  };
618
643
  let TextViewDesc = class TextViewDesc extends NodeViewDesc {
619
644
  constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, nodeDOM){
620
- super(parent, children, getPos, node, outerDeco, innerDeco, dom, null, nodeDOM, ()=>false, ()=>{
621
- /* Text nodes can't have node selections */ }, ()=>{
622
- /* Text nodes can't have node selections */ }, (mutation)=>{
623
- return mutation.type != "characterData" && mutation.type != "selection";
624
- });
645
+ super(parent, children, getPos, node, outerDeco, innerDeco, dom, null, nodeDOM);
625
646
  }
626
647
  parseRule() {
627
648
  let skip = this.nodeDOM.parentNode;
@@ -673,6 +694,63 @@ let TrailingHackViewDesc = class TrailingHackViewDesc extends ViewDesc {
673
694
  return this.dom.nodeName == "IMG";
674
695
  }
675
696
  };
697
+ // A separate subclass is used for customized node views, so that the
698
+ // extra checks only have to be made for nodes that are actually
699
+ // customized.
700
+ let CustomNodeViewDesc = class CustomNodeViewDesc extends NodeViewDesc {
701
+ spec;
702
+ constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec){
703
+ super(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM), this.spec = spec;
704
+ }
705
+ // A custom `update` method gets to decide whether the update goes
706
+ // through. If it does, and there's a `contentDOM` node, our logic
707
+ // updates the children.
708
+ update(node, outerDeco, innerDeco, view) {
709
+ if (this.dirty == NODE_DIRTY) return false;
710
+ if (this.spec.update && (this.node.type == node.type || this.spec.multiType)) {
711
+ const result = this.spec.update(node, outerDeco, innerDeco);
712
+ if (result) this.updateInner(node, outerDeco, innerDeco, view);
713
+ return result;
714
+ } else if (!this.contentDOM && !node.isLeaf) {
715
+ return false;
716
+ } else {
717
+ return super.update(node, outerDeco, innerDeco, view);
718
+ }
719
+ }
720
+ selectNode() {
721
+ this.spec.selectNode ? this.spec.selectNode() : super.selectNode();
722
+ }
723
+ deselectNode() {
724
+ this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
725
+ }
726
+ setSelection(anchor, head, view, force) {
727
+ this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root) : super.setSelection(anchor, head, view, force);
728
+ }
729
+ destroy() {
730
+ if (this.spec.destroy) this.spec.destroy();
731
+ super.destroy();
732
+ }
733
+ stopEvent(event) {
734
+ return this.spec.stopEvent ? this.spec.stopEvent(event) : false;
735
+ }
736
+ ignoreMutation(mutation) {
737
+ return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
738
+ }
739
+ };
740
+ let ReactNodeViewDesc = class ReactNodeViewDesc extends CustomNodeViewDesc {
741
+ updateChildren(_view, _pos) {
742
+ // React has already updated the children.
743
+ }
744
+ updateOuterDeco(outerDeco) {
745
+ // React has already updated the decorations.
746
+ this.outerDeco = outerDeco;
747
+ }
748
+ destroy() {
749
+ // React has already destroyed the children (if needed).
750
+ this.children = [];
751
+ super.destroy();
752
+ }
753
+ };
676
754
  function sameOuterDeco(a, b) {
677
755
  if (a.length != b.length) return false;
678
756
  // @ts-expect-error ...