@handlewithcare/react-prosemirror 2.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 (209) hide show
  1. package/LICENSE.txt +12 -0
  2. package/README.md +705 -0
  3. package/dist/cjs/browser.js +53 -0
  4. package/dist/cjs/components/ChildNodeViews.js +376 -0
  5. package/dist/cjs/components/CursorWrapper.js +91 -0
  6. package/dist/cjs/components/CustomNodeView.js +79 -0
  7. package/dist/cjs/components/DocNodeView.js +104 -0
  8. package/dist/cjs/components/LayoutGroup.js +111 -0
  9. package/dist/cjs/components/MarkView.js +115 -0
  10. package/dist/cjs/components/NativeWidgetView.js +109 -0
  11. package/dist/cjs/components/NodeView.js +196 -0
  12. package/dist/cjs/components/NodeViewComponentProps.js +4 -0
  13. package/dist/cjs/components/OutputSpec.js +88 -0
  14. package/dist/cjs/components/ProseMirror.js +103 -0
  15. package/dist/cjs/components/ProseMirrorDoc.js +92 -0
  16. package/dist/cjs/components/SeparatorHackView.js +100 -0
  17. package/dist/cjs/components/TextNodeView.js +112 -0
  18. package/dist/cjs/components/TrailingHackView.js +90 -0
  19. package/dist/cjs/components/WidgetView.js +95 -0
  20. package/dist/cjs/components/WidgetViewComponentProps.js +4 -0
  21. package/dist/cjs/components/__tests__/ProseMirror.composition.test.js +398 -0
  22. package/dist/cjs/components/__tests__/ProseMirror.domchange.test.js +270 -0
  23. package/dist/cjs/components/__tests__/ProseMirror.draw-decoration.test.js +1010 -0
  24. package/dist/cjs/components/__tests__/ProseMirror.draw.test.js +337 -0
  25. package/dist/cjs/components/__tests__/ProseMirror.node-view.test.js +315 -0
  26. package/dist/cjs/components/__tests__/ProseMirror.selection.test.js +444 -0
  27. package/dist/cjs/components/__tests__/ProseMirror.test.js +382 -0
  28. package/dist/cjs/contexts/ChildDescriptorsContext.js +19 -0
  29. package/dist/cjs/contexts/EditorContext.js +12 -0
  30. package/dist/cjs/contexts/EditorStateContext.js +12 -0
  31. package/dist/cjs/contexts/LayoutGroupContext.js +12 -0
  32. package/dist/cjs/contexts/NodeViewContext.js +12 -0
  33. package/dist/cjs/contexts/SelectNodeContext.js +12 -0
  34. package/dist/cjs/contexts/StopEventContext.js +12 -0
  35. package/dist/cjs/contexts/__tests__/DeferredLayoutEffects.test.js +141 -0
  36. package/dist/cjs/decorations/ReactWidgetType.js +58 -0
  37. package/dist/cjs/decorations/computeDocDeco.js +44 -0
  38. package/dist/cjs/decorations/internalTypes.js +4 -0
  39. package/dist/cjs/decorations/iterDeco.js +79 -0
  40. package/dist/cjs/decorations/viewDecorations.js +163 -0
  41. package/dist/cjs/dom.js +142 -0
  42. package/dist/cjs/hooks/__tests__/useEditorViewLayoutEffect.test.js +108 -0
  43. package/dist/cjs/hooks/useClientOnly.js +18 -0
  44. package/dist/cjs/hooks/useComponentEventListeners.js +39 -0
  45. package/dist/cjs/hooks/useEditor.js +287 -0
  46. package/dist/cjs/hooks/useEditorEffect.js +35 -0
  47. package/dist/cjs/hooks/useEditorEventCallback.js +33 -0
  48. package/dist/cjs/hooks/useEditorEventListener.js +34 -0
  49. package/dist/cjs/hooks/useEditorState.js +16 -0
  50. package/dist/cjs/hooks/useForceUpdate.js +15 -0
  51. package/dist/cjs/hooks/useLayoutGroupEffect.js +19 -0
  52. package/dist/cjs/hooks/useNodeViewDescriptor.js +115 -0
  53. package/dist/cjs/hooks/useReactKeys.js +17 -0
  54. package/dist/cjs/hooks/useSelectNode.js +28 -0
  55. package/dist/cjs/hooks/useStopEvent.js +24 -0
  56. package/dist/cjs/index.js +53 -0
  57. package/dist/cjs/package.json +3 -0
  58. package/dist/cjs/plugins/__tests__/reactKeys.test.js +81 -0
  59. package/dist/cjs/plugins/beforeInputPlugin.js +143 -0
  60. package/dist/cjs/plugins/componentEventListeners.js +35 -0
  61. package/dist/cjs/plugins/componentEventListenersPlugin.js +35 -0
  62. package/dist/cjs/plugins/reactKeys.js +96 -0
  63. package/dist/cjs/props.js +269 -0
  64. package/dist/cjs/selection/SelectionDOMObserver.js +174 -0
  65. package/dist/cjs/selection/hasFocusAndSelection.js +35 -0
  66. package/dist/cjs/selection/selectionFromDOM.js +77 -0
  67. package/dist/cjs/selection/selectionToDOM.js +226 -0
  68. package/dist/cjs/ssr.js +85 -0
  69. package/dist/cjs/testing/editorViewTestHelpers.js +111 -0
  70. package/dist/cjs/testing/setupProseMirrorView.js +94 -0
  71. package/dist/cjs/viewdesc.js +664 -0
  72. package/dist/esm/browser.js +43 -0
  73. package/dist/esm/components/ChildNodeViews.js +318 -0
  74. package/dist/esm/components/CursorWrapper.js +40 -0
  75. package/dist/esm/components/CustomNodeView.js +28 -0
  76. package/dist/esm/components/DocNodeView.js +53 -0
  77. package/dist/esm/components/LayoutGroup.js +66 -0
  78. package/dist/esm/components/MarkView.js +64 -0
  79. package/dist/esm/components/NativeWidgetView.js +58 -0
  80. package/dist/esm/components/NodeView.js +145 -0
  81. package/dist/esm/components/NodeViewComponentProps.js +1 -0
  82. package/dist/esm/components/OutputSpec.js +38 -0
  83. package/dist/esm/components/ProseMirror.js +52 -0
  84. package/dist/esm/components/ProseMirrorDoc.js +34 -0
  85. package/dist/esm/components/SeparatorHackView.js +49 -0
  86. package/dist/esm/components/TextNodeView.js +102 -0
  87. package/dist/esm/components/TrailingHackView.js +39 -0
  88. package/dist/esm/components/WidgetView.js +44 -0
  89. package/dist/esm/components/WidgetViewComponentProps.js +1 -0
  90. package/dist/esm/components/__tests__/ProseMirror.composition.test.js +395 -0
  91. package/dist/esm/components/__tests__/ProseMirror.domchange.test.js +266 -0
  92. package/dist/esm/components/__tests__/ProseMirror.draw-decoration.test.js +967 -0
  93. package/dist/esm/components/__tests__/ProseMirror.draw.test.js +294 -0
  94. package/dist/esm/components/__tests__/ProseMirror.node-view.test.js +272 -0
  95. package/dist/esm/components/__tests__/ProseMirror.selection.test.js +440 -0
  96. package/dist/esm/components/__tests__/ProseMirror.test.js +339 -0
  97. package/dist/esm/contexts/ChildDescriptorsContext.js +9 -0
  98. package/dist/esm/contexts/EditorContext.js +7 -0
  99. package/dist/esm/contexts/EditorStateContext.js +2 -0
  100. package/dist/esm/contexts/LayoutGroupContext.js +2 -0
  101. package/dist/esm/contexts/NodeViewContext.js +2 -0
  102. package/dist/esm/contexts/SelectNodeContext.js +2 -0
  103. package/dist/esm/contexts/StopEventContext.js +2 -0
  104. package/dist/esm/contexts/__tests__/DeferredLayoutEffects.test.js +98 -0
  105. package/dist/esm/decorations/ReactWidgetType.js +40 -0
  106. package/dist/esm/decorations/computeDocDeco.js +44 -0
  107. package/dist/esm/decorations/internalTypes.js +1 -0
  108. package/dist/esm/decorations/iterDeco.js +73 -0
  109. package/dist/esm/decorations/viewDecorations.js +163 -0
  110. package/dist/esm/dom.js +105 -0
  111. package/dist/esm/hooks/__tests__/useEditorViewLayoutEffect.test.js +99 -0
  112. package/dist/esm/hooks/useClientOnly.js +8 -0
  113. package/dist/esm/hooks/useComponentEventListeners.js +54 -0
  114. package/dist/esm/hooks/useEditor.js +278 -0
  115. package/dist/esm/hooks/useEditorEffect.js +38 -0
  116. package/dist/esm/hooks/useEditorEventCallback.js +35 -0
  117. package/dist/esm/hooks/useEditorEventListener.js +28 -0
  118. package/dist/esm/hooks/useEditorState.js +8 -0
  119. package/dist/esm/hooks/useForceUpdate.js +8 -0
  120. package/dist/esm/hooks/useLayoutGroupEffect.js +9 -0
  121. package/dist/esm/hooks/useNodeViewDescriptor.js +105 -0
  122. package/dist/esm/hooks/useReactKeys.js +7 -0
  123. package/dist/esm/hooks/useSelectNode.js +18 -0
  124. package/dist/esm/hooks/useStopEvent.js +14 -0
  125. package/dist/esm/index.js +11 -0
  126. package/dist/esm/plugins/__tests__/reactKeys.test.js +77 -0
  127. package/dist/esm/plugins/beforeInputPlugin.js +133 -0
  128. package/dist/esm/plugins/componentEventListeners.js +25 -0
  129. package/dist/esm/plugins/componentEventListenersPlugin.js +25 -0
  130. package/dist/esm/plugins/reactKeys.js +81 -0
  131. package/dist/esm/props.js +251 -0
  132. package/dist/esm/selection/SelectionDOMObserver.js +164 -0
  133. package/dist/esm/selection/hasFocusAndSelection.js +17 -0
  134. package/dist/esm/selection/selectionFromDOM.js +59 -0
  135. package/dist/esm/selection/selectionToDOM.js +196 -0
  136. package/dist/esm/ssr.js +82 -0
  137. package/dist/esm/testing/editorViewTestHelpers.js +88 -0
  138. package/dist/esm/testing/setupProseMirrorView.js +76 -0
  139. package/dist/esm/viewdesc.js +654 -0
  140. package/dist/tsconfig.tsbuildinfo +1 -0
  141. package/dist/types/browser.d.ts +15 -0
  142. package/dist/types/components/ChildNodeViews.d.ts +9 -0
  143. package/dist/types/components/CursorWrapper.d.ts +5 -0
  144. package/dist/types/components/CustomNodeView.d.ts +21 -0
  145. package/dist/types/components/DocNodeView.d.ts +20 -0
  146. package/dist/types/components/LayoutGroup.d.ts +12 -0
  147. package/dist/types/components/MarkView.d.ts +9 -0
  148. package/dist/types/components/NativeWidgetView.d.ts +8 -0
  149. package/dist/types/components/NodeView.d.ts +11 -0
  150. package/dist/types/components/NodeViewComponentProps.d.ts +12 -0
  151. package/dist/types/components/OutputSpec.d.ts +8 -0
  152. package/dist/types/components/ProseMirror.d.ts +15 -0
  153. package/dist/types/components/ProseMirrorDoc.d.ts +10 -0
  154. package/dist/types/components/SeparatorHackView.d.ts +6 -0
  155. package/dist/types/components/TextNodeView.d.ts +23 -0
  156. package/dist/types/components/TrailingHackView.d.ts +6 -0
  157. package/dist/types/components/WidgetView.d.ts +8 -0
  158. package/dist/types/components/WidgetViewComponentProps.d.ts +6 -0
  159. package/dist/types/components/__tests__/ProseMirror.composition.test.d.ts +1 -0
  160. package/dist/types/components/__tests__/ProseMirror.domchange.test.d.ts +1 -0
  161. package/dist/types/components/__tests__/ProseMirror.draw-decoration.test.d.ts +1 -0
  162. package/dist/types/components/__tests__/ProseMirror.draw.test.d.ts +1 -0
  163. package/dist/types/components/__tests__/ProseMirror.node-view.test.d.ts +1 -0
  164. package/dist/types/components/__tests__/ProseMirror.selection.test.d.ts +1 -0
  165. package/dist/types/components/__tests__/ProseMirror.test.d.ts +1 -0
  166. package/dist/types/contexts/ChildDescriptorsContext.d.ts +6 -0
  167. package/dist/types/contexts/EditorContext.d.ts +14 -0
  168. package/dist/types/contexts/EditorStateContext.d.ts +2 -0
  169. package/dist/types/contexts/LayoutGroupContext.d.ts +5 -0
  170. package/dist/types/contexts/NodeViewContext.d.ts +6 -0
  171. package/dist/types/contexts/SelectNodeContext.d.ts +3 -0
  172. package/dist/types/contexts/StopEventContext.d.ts +3 -0
  173. package/dist/types/contexts/__tests__/DeferredLayoutEffects.test.d.ts +1 -0
  174. package/dist/types/decorations/ReactWidgetType.d.ts +39 -0
  175. package/dist/types/decorations/computeDocDeco.d.ts +13 -0
  176. package/dist/types/decorations/internalTypes.d.ts +16 -0
  177. package/dist/types/decorations/iterDeco.d.ts +3 -0
  178. package/dist/types/decorations/viewDecorations.d.ts +13 -0
  179. package/dist/types/dom.d.ts +22 -0
  180. package/dist/types/hooks/__tests__/useEditorViewLayoutEffect.test.d.ts +1 -0
  181. package/dist/types/hooks/useClientOnly.d.ts +1 -0
  182. package/dist/types/hooks/useComponentEventListeners.d.ts +33 -0
  183. package/dist/types/hooks/useEditor.d.ts +66 -0
  184. package/dist/types/hooks/useEditorEffect.d.ts +17 -0
  185. package/dist/types/hooks/useEditorEventCallback.d.ts +15 -0
  186. package/dist/types/hooks/useEditorEventListener.d.ts +8 -0
  187. package/dist/types/hooks/useEditorState.d.ts +5 -0
  188. package/dist/types/hooks/useForceUpdate.d.ts +5 -0
  189. package/dist/types/hooks/useLayoutGroupEffect.d.ts +3 -0
  190. package/dist/types/hooks/useNodeViewDescriptor.d.ts +11 -0
  191. package/dist/types/hooks/useReactKeys.d.ts +5 -0
  192. package/dist/types/hooks/useSelectNode.d.ts +1 -0
  193. package/dist/types/hooks/useStopEvent.d.ts +2 -0
  194. package/dist/types/index.d.ts +12 -0
  195. package/dist/types/plugins/__tests__/reactKeys.test.d.ts +1 -0
  196. package/dist/types/plugins/beforeInputPlugin.d.ts +3 -0
  197. package/dist/types/plugins/componentEventListeners.d.ts +4 -0
  198. package/dist/types/plugins/componentEventListenersPlugin.d.ts +4 -0
  199. package/dist/types/plugins/reactKeys.d.ts +19 -0
  200. package/dist/types/props.d.ts +1174 -0
  201. package/dist/types/selection/SelectionDOMObserver.d.ts +34 -0
  202. package/dist/types/selection/hasFocusAndSelection.d.ts +3 -0
  203. package/dist/types/selection/selectionFromDOM.d.ts +4 -0
  204. package/dist/types/selection/selectionToDOM.d.ts +9 -0
  205. package/dist/types/ssr.d.ts +19 -0
  206. package/dist/types/testing/editorViewTestHelpers.d.ts +23 -0
  207. package/dist/types/testing/setupProseMirrorView.d.ts +2 -0
  208. package/dist/types/viewdesc.d.ts +131 -0
  209. package/package.json +113 -0
@@ -0,0 +1,145 @@
1
+ import React, { cloneElement, memo, useContext, useLayoutEffect, useMemo, useRef } from "react";
2
+ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { EditorContext } from "../contexts/EditorContext.js";
4
+ import { NodeViewContext } from "../contexts/NodeViewContext.js";
5
+ import { SelectNodeContext } from "../contexts/SelectNodeContext.js";
6
+ import { StopEventContext } from "../contexts/StopEventContext.js";
7
+ import { useNodeViewDescriptor } from "../hooks/useNodeViewDescriptor.js";
8
+ import { ChildNodeViews, wrapInDeco } from "./ChildNodeViews.js";
9
+ import { CustomNodeView } from "./CustomNodeView.js";
10
+ import { OutputSpec } from "./OutputSpec.js";
11
+ export const NodeView = /*#__PURE__*/ memo(function NodeView(param) {
12
+ let { outerDeco, getPos, node, innerDeco, ...props } = param;
13
+ const domRef = useRef(null);
14
+ const nodeDomRef = useRef(null);
15
+ const contentDomRef = useRef(null);
16
+ const getPosFunc = useRef(()=>getPos.current()).current;
17
+ // this is ill-conceived; should revisit
18
+ const initialNode = useRef(node);
19
+ const initialOuterDeco = useRef(outerDeco);
20
+ const initialInnerDeco = useRef(innerDeco);
21
+ const customNodeViewRootRef = useRef(null);
22
+ const customNodeViewRef = useRef(null);
23
+ // const state = useEditorState();
24
+ const { nodeViews } = useContext(NodeViewContext);
25
+ const { view } = useContext(EditorContext);
26
+ let element = null;
27
+ const Component = nodeViews[node.type.name];
28
+ const outputSpec = useMemo(()=>node.type.spec.toDOM?.(node), [
29
+ node
30
+ ]);
31
+ // TODO: Would be great to pull all of the custom node view stuff into
32
+ // a hook
33
+ const customNodeView = view?.someProp("nodeViews", (nodeViews)=>nodeViews?.[node.type.name]);
34
+ useLayoutEffect(()=>{
35
+ if (!customNodeViewRef.current || !customNodeViewRootRef.current) return;
36
+ const { dom } = customNodeViewRef.current;
37
+ nodeDomRef.current = customNodeViewRootRef.current;
38
+ customNodeViewRootRef.current.appendChild(dom);
39
+ return ()=>{
40
+ customNodeViewRef.current?.destroy?.();
41
+ };
42
+ }, []);
43
+ useLayoutEffect(()=>{
44
+ if (!customNodeView || !customNodeViewRef.current) return;
45
+ const { destroy, update } = customNodeViewRef.current;
46
+ const updated = update?.call(customNodeViewRef.current, node, outerDeco, innerDeco) ?? true;
47
+ if (updated) return;
48
+ destroy?.call(customNodeViewRef.current);
49
+ if (!customNodeViewRootRef.current) return;
50
+ initialNode.current = node;
51
+ initialOuterDeco.current = outerDeco;
52
+ initialInnerDeco.current = innerDeco;
53
+ customNodeViewRef.current = customNodeView(initialNode.current, // customNodeView will only be set if view is set, and we can only reach
54
+ // this line if customNodeView is set
55
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
56
+ view, ()=>getPos.current(), initialOuterDeco.current, initialInnerDeco.current);
57
+ const { dom } = customNodeViewRef.current;
58
+ nodeDomRef.current = customNodeViewRootRef.current;
59
+ customNodeViewRootRef.current.appendChild(dom);
60
+ }, [
61
+ customNodeView,
62
+ view,
63
+ innerDeco,
64
+ node,
65
+ outerDeco,
66
+ getPos
67
+ ]);
68
+ const { hasContentDOM, childDescriptors, setStopEvent, setSelectNode, nodeViewDescRef } = useNodeViewDescriptor(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
69
+ const finalProps = {
70
+ ...props,
71
+ ...!hasContentDOM && {
72
+ contentEditable: false
73
+ }
74
+ };
75
+ const nodeProps = useMemo(()=>({
76
+ node: node,
77
+ getPos: getPosFunc,
78
+ decorations: outerDeco,
79
+ innerDecorations: innerDeco
80
+ }), [
81
+ getPosFunc,
82
+ innerDeco,
83
+ node,
84
+ outerDeco
85
+ ]);
86
+ if (Component) {
87
+ element = /*#__PURE__*/ React.createElement(Component, {
88
+ ...finalProps,
89
+ ref: nodeDomRef,
90
+ nodeProps: nodeProps
91
+ }, /*#__PURE__*/ React.createElement(ChildNodeViews, {
92
+ getPos: getPos,
93
+ node: node,
94
+ innerDecorations: innerDeco
95
+ }));
96
+ } else if (customNodeView) {
97
+ element = /*#__PURE__*/ React.createElement(CustomNodeView, {
98
+ contentDomRef: contentDomRef,
99
+ customNodeView: customNodeView,
100
+ customNodeViewRef: customNodeViewRef,
101
+ customNodeViewRootRef: customNodeViewRootRef,
102
+ initialInnerDeco: initialInnerDeco,
103
+ initialNode: initialNode,
104
+ initialOuterDeco: initialOuterDeco,
105
+ node: node,
106
+ getPos: getPos,
107
+ innerDeco: innerDeco
108
+ });
109
+ } else {
110
+ if (outputSpec) {
111
+ element = /*#__PURE__*/ React.createElement(OutputSpec, {
112
+ ...finalProps,
113
+ ref: nodeDomRef,
114
+ outputSpec: outputSpec
115
+ }, /*#__PURE__*/ React.createElement(ChildNodeViews, {
116
+ getPos: getPos,
117
+ node: node,
118
+ innerDecorations: innerDeco
119
+ }));
120
+ }
121
+ }
122
+ if (!element) {
123
+ throw new Error(`Node spec for ${node.type.name} is missing toDOM`);
124
+ }
125
+ const decoratedElement = /*#__PURE__*/ cloneElement(outerDeco.reduce(wrapInDeco, element), // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
+ outerDeco.some((d)=>d.type.attrs.nodeName) ? {
127
+ ref: domRef
128
+ } : // we've already passed the domRef to the NodeView component
129
+ // as a prop
130
+ undefined);
131
+ const childContextValue = useMemo(()=>({
132
+ parentRef: nodeViewDescRef,
133
+ siblingsRef: childDescriptors
134
+ }), [
135
+ childDescriptors,
136
+ nodeViewDescRef
137
+ ]);
138
+ return /*#__PURE__*/ React.createElement(SelectNodeContext.Provider, {
139
+ value: setSelectNode
140
+ }, /*#__PURE__*/ React.createElement(StopEventContext.Provider, {
141
+ value: setStopEvent
142
+ }, /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
143
+ value: childContextValue
144
+ }, decoratedElement)));
145
+ });
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,38 @@
1
+ import React, { createElement, forwardRef, memo } from "react";
2
+ import { htmlAttrsToReactProps, mergeReactProps } from "../props.js";
3
+ const ForwardedOutputSpec = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function OutputSpec(param, ref) {
4
+ let { outputSpec, children, ...propOverrides } = param;
5
+ if (typeof outputSpec === "string") {
6
+ return /*#__PURE__*/ React.createElement(React.Fragment, null, outputSpec);
7
+ }
8
+ if (!Array.isArray(outputSpec)) {
9
+ throw new Error("@nytimes/react-prosemirror only supports strings and arrays in toDOM");
10
+ }
11
+ const tagSpec = outputSpec[0];
12
+ const tagName = tagSpec.replace(" ", ":");
13
+ const attrs = outputSpec[1];
14
+ let props = {
15
+ ref,
16
+ ...propOverrides
17
+ };
18
+ let start = 1;
19
+ if (attrs && typeof attrs === "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
20
+ start = 2;
21
+ props = mergeReactProps(htmlAttrsToReactProps(attrs), props);
22
+ }
23
+ const content = [];
24
+ for(let i = start; i < outputSpec.length; i++){
25
+ const child = outputSpec[i];
26
+ if (child === 0) {
27
+ if (i < outputSpec.length - 1 || i > start) {
28
+ throw new RangeError("Content hole must be the only child of its parent node");
29
+ }
30
+ return /*#__PURE__*/ createElement(tagName, props, children);
31
+ }
32
+ content.push(/*#__PURE__*/ React.createElement(ForwardedOutputSpec, {
33
+ outputSpec: child
34
+ }, children));
35
+ }
36
+ return /*#__PURE__*/ createElement(tagName, props, ...content);
37
+ }));
38
+ export { ForwardedOutputSpec as OutputSpec };
@@ -0,0 +1,52 @@
1
+ import { DecorationSet } from "prosemirror-view";
2
+ import React, { useMemo, useState } from "react";
3
+ import { EditorContext } from "../contexts/EditorContext.js";
4
+ import { EditorStateContext } from "../contexts/EditorStateContext.js";
5
+ import { NodeViewContext } from "../contexts/NodeViewContext.js";
6
+ import { computeDocDeco } from "../decorations/computeDocDeco.js";
7
+ import { viewDecorations } from "../decorations/viewDecorations.js";
8
+ import { useEditor } from "../hooks/useEditor.js";
9
+ import { LayoutGroup } from "./LayoutGroup.js";
10
+ import { DocNodeViewContext } from "./ProseMirrorDoc.js";
11
+ const EMPTY_OUTER_DECOS = [];
12
+ function ProseMirrorInner(param) {
13
+ let { className, children, nodeViews, customNodeViews, ...props } = param;
14
+ const [mount, setMount] = useState(null);
15
+ const { editor, state } = useEditor(mount, {
16
+ ...props,
17
+ nodeViews: customNodeViews
18
+ });
19
+ const innerDecos = editor.view ? viewDecorations(editor.view, editor.cursorWrapper) : DecorationSet.empty;
20
+ const outerDecos = editor.view ? computeDocDeco(editor.view) : EMPTY_OUTER_DECOS;
21
+ const nodeViewContextValue = useMemo(()=>({
22
+ nodeViews: nodeViews ?? {}
23
+ }), [
24
+ nodeViews
25
+ ]);
26
+ const docNodeViewContextValue = useMemo(()=>({
27
+ className: className,
28
+ setMount: setMount,
29
+ node: editor.view?.state.doc,
30
+ innerDeco: innerDecos,
31
+ outerDeco: outerDecos,
32
+ viewDesc: editor.docViewDescRef.current
33
+ }), [
34
+ className,
35
+ editor.docViewDescRef,
36
+ editor.view?.state.doc,
37
+ innerDecos,
38
+ outerDecos
39
+ ]);
40
+ return /*#__PURE__*/ React.createElement(EditorContext.Provider, {
41
+ value: editor
42
+ }, /*#__PURE__*/ React.createElement(EditorStateContext.Provider, {
43
+ value: state
44
+ }, /*#__PURE__*/ React.createElement(NodeViewContext.Provider, {
45
+ value: nodeViewContextValue
46
+ }, /*#__PURE__*/ React.createElement(DocNodeViewContext.Provider, {
47
+ value: docNodeViewContextValue
48
+ }, children))));
49
+ }
50
+ export function ProseMirror(props) {
51
+ return /*#__PURE__*/ React.createElement(LayoutGroup, null, /*#__PURE__*/ React.createElement(ProseMirrorInner, props));
52
+ }
@@ -0,0 +1,34 @@
1
+ import React, { createContext, forwardRef, useContext, useImperativeHandle, useMemo, useRef } from "react";
2
+ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { DocNodeView } from "./DocNodeView.js";
4
+ export const DocNodeViewContext = /*#__PURE__*/ createContext(null);
5
+ function ProseMirrorDoc(param, ref) {
6
+ let { as, ...props } = param;
7
+ const childDescriptors = useRef([]);
8
+ const innerRef = useRef(null);
9
+ const { setMount, ...docProps } = useContext(DocNodeViewContext);
10
+ const viewDescRef = useRef(undefined);
11
+ useImperativeHandle(ref, ()=>{
12
+ return innerRef.current;
13
+ }, []);
14
+ const childContextValue = useMemo(()=>({
15
+ parentRef: viewDescRef,
16
+ siblingsRef: childDescriptors
17
+ }), [
18
+ childDescriptors,
19
+ viewDescRef
20
+ ]);
21
+ return /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
22
+ value: childContextValue
23
+ }, /*#__PURE__*/ React.createElement(DocNodeView, {
24
+ ref: (el)=>{
25
+ innerRef.current = el;
26
+ setMount(el);
27
+ },
28
+ ...props,
29
+ ...docProps,
30
+ as: as
31
+ }));
32
+ }
33
+ const ForwardedProseMirrorDoc = /*#__PURE__*/ forwardRef(ProseMirrorDoc);
34
+ export { ForwardedProseMirrorDoc as ProseMirrorDoc };
@@ -0,0 +1,49 @@
1
+ import React, { useContext, useLayoutEffect, useRef, useState } from "react";
2
+ import { browser } from "../browser.js";
3
+ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
4
+ import { TrailingHackViewDesc, sortViewDescs } from "../viewdesc.js";
5
+ export function SeparatorHackView(param) {
6
+ let { getPos } = param;
7
+ const { siblingsRef, parentRef } = useContext(ChildDescriptorsContext);
8
+ const viewDescRef = useRef(null);
9
+ const ref = useRef(null);
10
+ const [shouldRender, setShouldRender] = useState(false);
11
+ useLayoutEffect(()=>{
12
+ const siblings = siblingsRef.current;
13
+ return ()=>{
14
+ if (!viewDescRef.current) return;
15
+ if (siblings.includes(viewDescRef.current)) {
16
+ const index = siblings.indexOf(viewDescRef.current);
17
+ siblings.splice(index, 1);
18
+ }
19
+ };
20
+ }, [
21
+ siblingsRef
22
+ ]);
23
+ // There's no risk of an infinite loop here, because
24
+ // we call setShouldRender conditionally
25
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
+ useLayoutEffect(()=>{
27
+ const lastSibling = siblingsRef.current[siblingsRef.current.length - 1];
28
+ if ((browser.safari || browser.chrome) && lastSibling?.dom?.contentEditable == "false") {
29
+ setShouldRender(true);
30
+ return;
31
+ }
32
+ if (!ref.current) return;
33
+ if (!viewDescRef.current) {
34
+ viewDescRef.current = new TrailingHackViewDesc(parentRef.current, [], ()=>getPos.current(), ref.current, null);
35
+ } else {
36
+ viewDescRef.current.parent = parentRef.current;
37
+ viewDescRef.current.dom = ref.current;
38
+ viewDescRef.current.getPos = ()=>getPos.current();
39
+ }
40
+ if (!siblingsRef.current.includes(viewDescRef.current)) {
41
+ siblingsRef.current.push(viewDescRef.current);
42
+ }
43
+ siblingsRef.current.sort(sortViewDescs);
44
+ });
45
+ return shouldRender ? /*#__PURE__*/ React.createElement("img", {
46
+ ref: ref,
47
+ className: "ProseMirror-separator"
48
+ }) : null;
49
+ }
@@ -0,0 +1,102 @@
1
+ import { DecorationSet } from "prosemirror-view";
2
+ import { Component } from "react";
3
+ import { findDOMNode } from "react-dom";
4
+ import { CompositionViewDesc, TextViewDesc, sortViewDescs } from "../viewdesc.js";
5
+ import { wrapInDeco } from "./ChildNodeViews.js";
6
+ function shallowEqual(objA, objB) {
7
+ if (objA === objB) {
8
+ return true;
9
+ }
10
+ if (!objA || !objB) {
11
+ return false;
12
+ }
13
+ const aKeys = Object.keys(objA);
14
+ const bKeys = Object.keys(objB);
15
+ const len = aKeys.length;
16
+ if (bKeys.length !== len) {
17
+ return false;
18
+ }
19
+ for(let i = 0; i < len; i++){
20
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
+ const key = aKeys[i];
22
+ if (objA[key] !== objB[key] || !Object.prototype.hasOwnProperty.call(objB, key)) {
23
+ return false;
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+ export class TextNodeView extends Component {
29
+ viewDescRef = null;
30
+ renderRef = null;
31
+ updateEffect() {
32
+ const { view, decorations, siblingsRef, parentRef, getPos, node } = this.props;
33
+ // There simply is no other way to ref a text node
34
+ // eslint-disable-next-line react/no-find-dom-node
35
+ const dom = findDOMNode(this);
36
+ // We only need to explicitly create a CompositionViewDesc
37
+ // when a composition was started that produces a new text node.
38
+ // Otherwise we just rely on re-rendering the renderRef
39
+ if (!dom) {
40
+ if (!view?.composing) return;
41
+ this.viewDescRef = new CompositionViewDesc(parentRef.current, ()=>getPos.current(), // These are just placeholders/dummies. We can't
42
+ // actually find the correct DOM nodes from here,
43
+ // so we let our parent do it.
44
+ // Passing a valid element here just so that the
45
+ // ViewDesc constructor doesn't blow up.
46
+ document.createElement("div"), document.createTextNode(node.text ?? ""), node.text ?? "");
47
+ return;
48
+ }
49
+ let textNode = dom;
50
+ while(textNode.firstChild){
51
+ textNode = textNode.firstChild;
52
+ }
53
+ if (!this.viewDescRef || this.viewDescRef instanceof CompositionViewDesc) {
54
+ this.viewDescRef = new TextViewDesc(undefined, [], ()=>getPos.current(), node, decorations, DecorationSet.empty, dom, textNode);
55
+ } else {
56
+ this.viewDescRef.parent = parentRef.current;
57
+ this.viewDescRef.children = [];
58
+ this.viewDescRef.node = node;
59
+ this.viewDescRef.getPos = ()=>getPos.current();
60
+ this.viewDescRef.outerDeco = decorations;
61
+ this.viewDescRef.innerDeco = DecorationSet.empty;
62
+ this.viewDescRef.dom = dom;
63
+ // @ts-expect-error We have our own ViewDesc implementations
64
+ this.viewDescRef.dom.pmViewDesc = this.viewDescRef;
65
+ this.viewDescRef.nodeDOM = textNode;
66
+ }
67
+ if (!siblingsRef.current.includes(this.viewDescRef)) {
68
+ siblingsRef.current.push(this.viewDescRef);
69
+ }
70
+ siblingsRef.current.sort(sortViewDescs);
71
+ }
72
+ shouldComponentUpdate(nextProps) {
73
+ return !shallowEqual(this.props, nextProps);
74
+ }
75
+ componentDidMount() {
76
+ this.updateEffect();
77
+ }
78
+ componentDidUpdate() {
79
+ this.updateEffect();
80
+ }
81
+ componentWillUnmount() {
82
+ const { siblingsRef } = this.props;
83
+ if (!this.viewDescRef) return;
84
+ if (siblingsRef.current.includes(this.viewDescRef)) {
85
+ const index = siblingsRef.current.indexOf(this.viewDescRef);
86
+ siblingsRef.current.splice(index, 1);
87
+ }
88
+ }
89
+ render() {
90
+ const { view, getPos, node, decorations } = this.props;
91
+ // During a composition, it's crucial that we don't try to
92
+ // update the DOM that the user is working in. If there's
93
+ // an active composition and the selection is in this node,
94
+ // we freeze the DOM of this element so that it doesn't
95
+ // interrupt the composition
96
+ if (view?.composing && view.state.selection.from >= getPos.current() && view.state.selection.from <= getPos.current() + node.nodeSize) {
97
+ return this.renderRef;
98
+ }
99
+ this.renderRef = decorations.reduce(wrapInDeco, node.text);
100
+ return this.renderRef;
101
+ }
102
+ }
@@ -0,0 +1,39 @@
1
+ import React, { useContext, useLayoutEffect, useRef } from "react";
2
+ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { TrailingHackViewDesc, sortViewDescs } from "../viewdesc.js";
4
+ export function TrailingHackView(param) {
5
+ let { getPos } = param;
6
+ const { siblingsRef, parentRef } = useContext(ChildDescriptorsContext);
7
+ const viewDescRef = useRef(null);
8
+ const ref = useRef(null);
9
+ useLayoutEffect(()=>{
10
+ const siblings = siblingsRef.current;
11
+ return ()=>{
12
+ if (!viewDescRef.current) return;
13
+ if (siblings.includes(viewDescRef.current)) {
14
+ const index = siblings.indexOf(viewDescRef.current);
15
+ siblings.splice(index, 1);
16
+ }
17
+ };
18
+ }, [
19
+ siblingsRef
20
+ ]);
21
+ useLayoutEffect(()=>{
22
+ if (!ref.current) return;
23
+ if (!viewDescRef.current) {
24
+ viewDescRef.current = new TrailingHackViewDesc(parentRef.current, [], ()=>getPos.current(), ref.current, null);
25
+ } else {
26
+ viewDescRef.current.parent = parentRef.current;
27
+ viewDescRef.current.dom = ref.current;
28
+ viewDescRef.current.getPos = ()=>getPos.current();
29
+ }
30
+ if (!siblingsRef.current.includes(viewDescRef.current)) {
31
+ siblingsRef.current.push(viewDescRef.current);
32
+ }
33
+ siblingsRef.current.sort(sortViewDescs);
34
+ });
35
+ return /*#__PURE__*/ React.createElement("br", {
36
+ ref: ref,
37
+ className: "ProseMirror-trailingBreak"
38
+ });
39
+ }
@@ -0,0 +1,44 @@
1
+ import React, { useContext, useLayoutEffect, useRef } from "react";
2
+ import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
3
+ import { WidgetViewDesc, sortViewDescs } from "../viewdesc.js";
4
+ export function WidgetView(param) {
5
+ let { widget, getPos } = param;
6
+ const { siblingsRef, parentRef } = useContext(ChildDescriptorsContext);
7
+ const viewDescRef = useRef(null);
8
+ const getPosFunc = useRef(()=>getPos.current()).current;
9
+ const domRef = useRef(null);
10
+ useLayoutEffect(()=>{
11
+ const siblings = siblingsRef.current;
12
+ return ()=>{
13
+ if (!viewDescRef.current) return;
14
+ if (siblings.includes(viewDescRef.current)) {
15
+ const index = siblings.indexOf(viewDescRef.current);
16
+ siblings.splice(index, 1);
17
+ }
18
+ };
19
+ }, [
20
+ siblingsRef
21
+ ]);
22
+ useLayoutEffect(()=>{
23
+ if (!domRef.current) return;
24
+ if (!viewDescRef.current) {
25
+ viewDescRef.current = new WidgetViewDesc(parentRef.current, ()=>getPos.current(), widget, domRef.current);
26
+ } else {
27
+ viewDescRef.current.parent = parentRef.current;
28
+ viewDescRef.current.widget = widget;
29
+ viewDescRef.current.getPos = ()=>getPos.current();
30
+ viewDescRef.current.dom = domRef.current;
31
+ }
32
+ if (!siblingsRef.current.includes(viewDescRef.current)) {
33
+ siblingsRef.current.push(viewDescRef.current);
34
+ }
35
+ siblingsRef.current.sort(sortViewDescs);
36
+ });
37
+ const { Component } = widget.type;
38
+ return Component && /*#__PURE__*/ React.createElement(Component, {
39
+ ref: domRef,
40
+ widget: widget,
41
+ getPos: getPosFunc,
42
+ contentEditable: false
43
+ });
44
+ }
@@ -0,0 +1 @@
1
+ export { };