@handlewithcare/react-prosemirror 2.4.10 → 2.4.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/cjs/components/Editor.js +28 -0
- package/dist/cjs/components/NodeViews.js +73 -0
- package/dist/cjs/{contexts/__tests__/DeferredLayoutEffects.test.js → components/__tests__/LayoutGroup.test.js} +2 -2
- package/dist/cjs/components/__tests__/ProseMirror.test.js +136 -263
- package/dist/cjs/contexts/NodeViewsContext.js +10 -0
- package/dist/cjs/hooks/__tests__/useEditorViewLayoutEffect.test.js +27 -28
- package/dist/cjs/hooks/__tests__/useNodeViews.test.js +159 -0
- package/dist/cjs/hooks/useEditor.js +2 -4
- package/dist/cjs/hooks/useEditorView.js +100 -0
- package/dist/cjs/hooks/useNodePos.js +69 -0
- package/dist/cjs/hooks/useNodeViews.js +100 -0
- package/dist/cjs/nodeViews/createReactNodeViewConstructor.js +244 -0
- package/dist/cjs/nodeViews/phrasingContentTags.js +57 -0
- package/dist/cjs/plugins/__tests__/react.test.js +139 -0
- package/dist/cjs/plugins/react.js +71 -0
- package/dist/esm/components/Editor.js +15 -0
- package/dist/esm/components/NodeViews.js +26 -0
- package/dist/esm/{contexts/__tests__/DeferredLayoutEffects.test.js → components/__tests__/LayoutGroup.test.js} +2 -2
- package/dist/esm/components/__tests__/ProseMirror.test.js +135 -267
- package/dist/esm/contexts/NodeViewsContext.js +9 -0
- package/dist/esm/hooks/__tests__/useEditorViewLayoutEffect.test.js +27 -28
- package/dist/esm/hooks/__tests__/useNodeViews.test.js +116 -0
- package/dist/esm/hooks/useEditor.js +2 -4
- package/dist/esm/hooks/useEditorView.js +99 -0
- package/dist/esm/hooks/useNodePos.js +16 -0
- package/dist/esm/hooks/useNodeViews.js +53 -0
- package/dist/esm/nodeViews/createReactNodeViewConstructor.js +214 -0
- package/dist/esm/nodeViews/phrasingContentTags.js +49 -0
- package/dist/esm/plugins/__tests__/react.test.js +135 -0
- package/dist/esm/plugins/react.js +64 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/components/Editor.d.ts +7 -0
- package/dist/types/components/NodeViews.d.ts +6 -0
- package/dist/types/components/__tests__/LayoutGroup.test.d.ts +1 -0
- package/dist/types/contexts/NodeViewsContext.d.ts +19 -0
- package/dist/types/decorations/ReactWidgetType.d.ts +1 -0
- package/dist/types/hooks/__tests__/useNodeViews.test.d.ts +1 -0
- package/dist/types/hooks/useEditorView.d.ts +23 -0
- package/dist/types/hooks/useNodePos.d.ts +9 -0
- package/dist/types/hooks/useNodeViews.d.ts +5 -0
- package/dist/types/nodeViews/createReactNodeViewConstructor.d.ts +48 -0
- package/dist/types/nodeViews/phrasingContentTags.d.ts +1 -0
- package/dist/types/plugins/__tests__/react.test.d.ts +1 -0
- package/dist/types/plugins/react.d.ts +21 -0
- package/dist/types/props.d.ts +27 -27
- package/package.json +1 -1
- package/dist/cjs/components/__tests__/ProseMirror.composition.test.js +0 -398
- package/dist/cjs/components/__tests__/ProseMirror.domchange.test.js +0 -270
- package/dist/cjs/components/__tests__/ProseMirror.draw-decoration.test.js +0 -1010
- package/dist/cjs/components/__tests__/ProseMirror.draw.test.js +0 -337
- package/dist/cjs/components/__tests__/ProseMirror.node-view.test.js +0 -315
- package/dist/cjs/components/__tests__/ProseMirror.selection.test.js +0 -444
- package/dist/cjs/plugins/__tests__/reactKeys.test.js +0 -81
- package/dist/esm/components/__tests__/ProseMirror.composition.test.js +0 -395
- package/dist/esm/components/__tests__/ProseMirror.domchange.test.js +0 -266
- package/dist/esm/components/__tests__/ProseMirror.draw-decoration.test.js +0 -967
- package/dist/esm/components/__tests__/ProseMirror.draw.test.js +0 -294
- package/dist/esm/components/__tests__/ProseMirror.node-view.test.js +0 -272
- package/dist/esm/components/__tests__/ProseMirror.selection.test.js +0 -440
- package/dist/esm/plugins/__tests__/reactKeys.test.js +0 -77
package/README.md
CHANGED
|
@@ -63,6 +63,22 @@ yarn add @handlewithcare/react-prosemirror \
|
|
|
63
63
|
prosemirror-model
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
_Note_: React ProseMirror needs the prosemirror-view stylesheet just as a
|
|
67
|
+
vanilla ProseMirror set up would. How this stylesheet gets imported can vary
|
|
68
|
+
based on the application, but may be as simple as:
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
/* editor.css */
|
|
72
|
+
@import "prosemirror-view/style/prosemirror.css";
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
// Editor.tsx
|
|
79
|
+
import "prosemirror-view/style/prosemirror.css";
|
|
80
|
+
```
|
|
81
|
+
|
|
66
82
|
<!-- toc -->
|
|
67
83
|
|
|
68
84
|
- [The Problem](#the-problem)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "Editor", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>Editor
|
|
8
|
+
});
|
|
9
|
+
const _react = /*#__PURE__*/ _interopRequireDefault(require("react"));
|
|
10
|
+
const _editorContextJs = require("../contexts/EditorContext.js");
|
|
11
|
+
const _useEditorViewJs = require("../hooks/useEditorView.js");
|
|
12
|
+
const _useNodeViewsJs = require("../hooks/useNodeViews.js");
|
|
13
|
+
function _interopRequireDefault(obj) {
|
|
14
|
+
return obj && obj.__esModule ? obj : {
|
|
15
|
+
default: obj
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function Editor(param) {
|
|
19
|
+
let { mount , children , ...options } = param;
|
|
20
|
+
const { nodeViews , nodeViewsComponent } = (0, _useNodeViewsJs.useNodeViews)(options.nodeViews);
|
|
21
|
+
const value = (0, _useEditorViewJs.useEditorView)(mount, {
|
|
22
|
+
...options,
|
|
23
|
+
nodeViews
|
|
24
|
+
});
|
|
25
|
+
return /*#__PURE__*/ _react.default.createElement(_editorContextJs.EditorContext.Provider, {
|
|
26
|
+
value: value
|
|
27
|
+
}, children, nodeViewsComponent);
|
|
28
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "NodeViews", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>NodeViews
|
|
8
|
+
});
|
|
9
|
+
const _react = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
10
|
+
const _nodeViewsContextJs = require("../contexts/NodeViewsContext.js");
|
|
11
|
+
const _useEditorEffectJs = require("../hooks/useEditorEffect.js");
|
|
12
|
+
const _reactJs = require("../plugins/react.js");
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
14
|
+
if (typeof WeakMap !== "function") return null;
|
|
15
|
+
var cacheBabelInterop = new WeakMap();
|
|
16
|
+
var cacheNodeInterop = new WeakMap();
|
|
17
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
18
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
19
|
+
})(nodeInterop);
|
|
20
|
+
}
|
|
21
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
22
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
26
|
+
return {
|
|
27
|
+
default: obj
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
31
|
+
if (cache && cache.has(obj)) {
|
|
32
|
+
return cache.get(obj);
|
|
33
|
+
}
|
|
34
|
+
var newObj = {};
|
|
35
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
36
|
+
for(var key in obj){
|
|
37
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
38
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
39
|
+
if (desc && (desc.get || desc.set)) {
|
|
40
|
+
Object.defineProperty(newObj, key, desc);
|
|
41
|
+
} else {
|
|
42
|
+
newObj[key] = obj[key];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
newObj.default = obj;
|
|
47
|
+
if (cache) {
|
|
48
|
+
cache.set(obj, newObj);
|
|
49
|
+
}
|
|
50
|
+
return newObj;
|
|
51
|
+
}
|
|
52
|
+
function NodeViews(param) {
|
|
53
|
+
let { portals } = param;
|
|
54
|
+
const rootRegisteredPortals = portals[_reactJs.ROOT_NODE_KEY];
|
|
55
|
+
const [rootPortals, setRootPortals] = (0, _react.useState)(rootRegisteredPortals?.map((param)=>{
|
|
56
|
+
let { portal } = param;
|
|
57
|
+
return portal;
|
|
58
|
+
}) ?? []);
|
|
59
|
+
// `getPos` is technically derived from the EditorView
|
|
60
|
+
// state, so it's not safe to call until after the EditorView
|
|
61
|
+
// has been updated
|
|
62
|
+
(0, _useEditorEffectJs.useEditorEffect)(()=>{
|
|
63
|
+
setRootPortals(rootRegisteredPortals?.sort((a, b)=>a.getPos() - b.getPos()).map((param)=>{
|
|
64
|
+
let { portal } = param;
|
|
65
|
+
return portal;
|
|
66
|
+
}) ?? []);
|
|
67
|
+
}, [
|
|
68
|
+
rootRegisteredPortals
|
|
69
|
+
]);
|
|
70
|
+
return /*#__PURE__*/ _react.default.createElement(_nodeViewsContextJs.NodeViewsContext.Provider, {
|
|
71
|
+
value: portals
|
|
72
|
+
}, rootPortals);
|
|
73
|
+
}
|
|
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
});
|
|
5
5
|
const _react = require("@testing-library/react");
|
|
6
6
|
const _react1 = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
7
|
-
const _layoutGroupJs = require("../../components/LayoutGroup.js");
|
|
8
7
|
const _useLayoutGroupEffectJs = require("../../hooks/useLayoutGroupEffect.js");
|
|
8
|
+
const _layoutGroupJs = require("../LayoutGroup.js");
|
|
9
9
|
function _getRequireWildcardCache(nodeInterop) {
|
|
10
10
|
if (typeof WeakMap !== "function") return null;
|
|
11
11
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -45,7 +45,7 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
45
45
|
}
|
|
46
46
|
return newObj;
|
|
47
47
|
}
|
|
48
|
-
describe("
|
|
48
|
+
describe("LayoutGroup", ()=>{
|
|
49
49
|
jest.useFakeTimers("modern");
|
|
50
50
|
it("registers multiple effects and runs them", ()=>{
|
|
51
51
|
function Parent() {
|
|
@@ -1,31 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
const _react = require("@testing-library/react");
|
|
6
|
+
const _userEvent = /*#__PURE__*/ _interopRequireDefault(require("@testing-library/user-event"));
|
|
6
7
|
const _prosemirrorModel = require("prosemirror-model");
|
|
7
8
|
const _prosemirrorState = require("prosemirror-state");
|
|
8
|
-
const _prosemirrorTestBuilder = require("prosemirror-test-builder");
|
|
9
9
|
const _react1 = /*#__PURE__*/ _interopRequireWildcard(require("react"));
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const _reactKeysJs = require("../../plugins/reactKeys.js");
|
|
13
|
-
const _editorViewTestHelpersJs = require("../../testing/editorViewTestHelpers.js");
|
|
10
|
+
const _reactJs = require("../../plugins/react.js");
|
|
11
|
+
const _setupProseMirrorViewJs = require("../../testing/setupProseMirrorView.js");
|
|
14
12
|
const _proseMirrorJs = require("../ProseMirror.js");
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
for(var i = 1; i < arguments.length; i++){
|
|
19
|
-
var source = arguments[i];
|
|
20
|
-
for(var key in source){
|
|
21
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
22
|
-
target[key] = source[key];
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return target;
|
|
13
|
+
function _interopRequireDefault(obj) {
|
|
14
|
+
return obj && obj.__esModule ? obj : {
|
|
15
|
+
default: obj
|
|
27
16
|
};
|
|
28
|
-
return _extends.apply(this, arguments);
|
|
29
17
|
}
|
|
30
18
|
function _getRequireWildcardCache(nodeInterop) {
|
|
31
19
|
if (typeof WeakMap !== "function") return null;
|
|
@@ -66,7 +54,15 @@ function _interopRequireWildcard(obj, nodeInterop) {
|
|
|
66
54
|
}
|
|
67
55
|
return newObj;
|
|
68
56
|
}
|
|
57
|
+
// Mock `ReactDOM.flushSync` to call `act` to flush updates from DOM mutations.
|
|
58
|
+
jest.mock("react-dom", ()=>({
|
|
59
|
+
...jest.requireActual("react-dom"),
|
|
60
|
+
flushSync: (fn)=>(0, _react.act)(fn)
|
|
61
|
+
}));
|
|
69
62
|
describe("ProseMirror", ()=>{
|
|
63
|
+
beforeAll(()=>{
|
|
64
|
+
(0, _setupProseMirrorViewJs.setupProseMirrorView)();
|
|
65
|
+
});
|
|
70
66
|
it("renders a contenteditable", async ()=>{
|
|
71
67
|
const schema = new _prosemirrorModel.Schema({
|
|
72
68
|
nodes: {
|
|
@@ -76,35 +72,26 @@ describe("ProseMirror", ()=>{
|
|
|
76
72
|
}
|
|
77
73
|
}
|
|
78
74
|
});
|
|
79
|
-
const
|
|
75
|
+
const defaultState = _prosemirrorState.EditorState.create({
|
|
80
76
|
schema
|
|
81
77
|
});
|
|
82
78
|
function TestEditor() {
|
|
79
|
+
const [mount, setMount] = (0, _react1.useState)(null);
|
|
83
80
|
return /*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
mount: mount,
|
|
82
|
+
defaultState: defaultState
|
|
83
|
+
}, /*#__PURE__*/ _react1.default.createElement("div", {
|
|
84
|
+
"data-testid": "editor",
|
|
85
|
+
ref: setMount
|
|
87
86
|
}));
|
|
88
87
|
}
|
|
88
|
+
const user = _userEvent.default.setup();
|
|
89
89
|
(0, _react.render)(/*#__PURE__*/ _react1.default.createElement(TestEditor, null));
|
|
90
90
|
const editor = _react.screen.getByTestId("editor");
|
|
91
|
-
|
|
92
|
-
await browser.keys("H");
|
|
93
|
-
await browser.keys("e");
|
|
94
|
-
await browser.keys("l");
|
|
95
|
-
await browser.keys("l");
|
|
96
|
-
await browser.keys("o");
|
|
97
|
-
await browser.keys(",");
|
|
98
|
-
await browser.keys(" ");
|
|
99
|
-
await browser.keys("w");
|
|
100
|
-
await browser.keys("o");
|
|
101
|
-
await browser.keys("r");
|
|
102
|
-
await browser.keys("l");
|
|
103
|
-
await browser.keys("d");
|
|
104
|
-
await browser.keys("!");
|
|
91
|
+
await user.type(editor, "Hello, world!");
|
|
105
92
|
expect(editor.textContent).toBe("Hello, world!");
|
|
106
93
|
});
|
|
107
|
-
it("supports
|
|
94
|
+
it("supports observing transaction dispatch", async ()=>{
|
|
108
95
|
const schema = new _prosemirrorModel.Schema({
|
|
109
96
|
nodes: {
|
|
110
97
|
text: {},
|
|
@@ -113,270 +100,156 @@ describe("ProseMirror", ()=>{
|
|
|
113
100
|
}
|
|
114
101
|
}
|
|
115
102
|
});
|
|
116
|
-
|
|
103
|
+
const defaultState = _prosemirrorState.EditorState.create({
|
|
117
104
|
schema
|
|
118
105
|
});
|
|
106
|
+
const dispatchTransaction = jest.fn();
|
|
119
107
|
function TestEditor() {
|
|
120
|
-
const [
|
|
108
|
+
const [mount, setMount] = (0, _react1.useState)(null);
|
|
109
|
+
return /*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
110
|
+
mount: mount,
|
|
111
|
+
defaultState: defaultState,
|
|
112
|
+
dispatchTransaction: dispatchTransaction
|
|
113
|
+
}, /*#__PURE__*/ _react1.default.createElement("div", {
|
|
114
|
+
"data-testid": "editor",
|
|
115
|
+
ref: setMount
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
const user = _userEvent.default.setup();
|
|
119
|
+
(0, _react.render)(/*#__PURE__*/ _react1.default.createElement(TestEditor, null));
|
|
120
|
+
const editor = _react.screen.getByTestId("editor");
|
|
121
|
+
await user.type(editor, "Hello, world!");
|
|
122
|
+
expect(editor.textContent).toBe("Hello, world!");
|
|
123
|
+
expect(dispatchTransaction).toHaveBeenCalledTimes(13);
|
|
124
|
+
});
|
|
125
|
+
it("supports controlling the editor state", async ()=>{
|
|
126
|
+
const schema = new _prosemirrorModel.Schema({
|
|
127
|
+
nodes: {
|
|
128
|
+
text: {},
|
|
129
|
+
doc: {
|
|
130
|
+
content: "text*"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
let observedState = _prosemirrorState.EditorState.create({
|
|
135
|
+
schema
|
|
136
|
+
});
|
|
137
|
+
function TestEditor() {
|
|
138
|
+
const [state, setState] = (0, _react1.useState)(observedState);
|
|
139
|
+
const [mount, setMount] = (0, _react1.useState)(null);
|
|
121
140
|
(0, _react1.useEffect)(()=>{
|
|
122
|
-
|
|
141
|
+
observedState = state;
|
|
123
142
|
}, [
|
|
124
|
-
|
|
143
|
+
state
|
|
125
144
|
]);
|
|
126
145
|
return /*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
146
|
+
mount: mount,
|
|
147
|
+
state: state,
|
|
148
|
+
dispatchTransaction: (tr)=>{
|
|
149
|
+
setState((s)=>s.apply(tr));
|
|
150
|
+
}
|
|
151
|
+
}, /*#__PURE__*/ _react1.default.createElement("div", {
|
|
152
|
+
"data-testid": "editor",
|
|
153
|
+
ref: setMount
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
const user = _userEvent.default.setup();
|
|
157
|
+
(0, _react.render)(/*#__PURE__*/ _react1.default.createElement(TestEditor, null));
|
|
158
|
+
const editor = _react.screen.getByTestId("editor");
|
|
159
|
+
await user.type(editor, "Hello, world!");
|
|
160
|
+
expect(observedState.doc.textContent).toBe("Hello, world!");
|
|
161
|
+
});
|
|
162
|
+
it("updates props atomically", async ()=>{
|
|
163
|
+
const schema = new _prosemirrorModel.Schema({
|
|
164
|
+
nodes: {
|
|
165
|
+
text: {},
|
|
166
|
+
doc: {
|
|
167
|
+
content: "text*"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const defaultState = _prosemirrorState.EditorState.create({
|
|
172
|
+
schema
|
|
173
|
+
});
|
|
174
|
+
let allStatesMatched = true;
|
|
175
|
+
function TestEditor() {
|
|
176
|
+
const [state, setState] = (0, _react1.useState)(defaultState);
|
|
177
|
+
const [mount, setMount] = (0, _react1.useState)(null);
|
|
178
|
+
// Check that function props get invoked with the latest React state.
|
|
179
|
+
const editable = (viewState)=>{
|
|
180
|
+
allStatesMatched &&= viewState === state;
|
|
181
|
+
return true;
|
|
182
|
+
};
|
|
183
|
+
return /*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
184
|
+
mount: mount,
|
|
185
|
+
editable: editable,
|
|
186
|
+
state: state,
|
|
187
|
+
dispatchTransaction: (tr)=>{
|
|
188
|
+
setState((s)=>s.apply(tr));
|
|
189
|
+
}
|
|
190
|
+
}, /*#__PURE__*/ _react1.default.createElement("div", {
|
|
191
|
+
"data-testid": "editor",
|
|
192
|
+
ref: setMount
|
|
131
193
|
}));
|
|
132
194
|
}
|
|
195
|
+
const user = _userEvent.default.setup();
|
|
133
196
|
(0, _react.render)(/*#__PURE__*/ _react1.default.createElement(TestEditor, null));
|
|
134
197
|
const editor = _react.screen.getByTestId("editor");
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
await browser.keys("e");
|
|
138
|
-
await browser.keys("l");
|
|
139
|
-
await browser.keys("l");
|
|
140
|
-
await browser.keys("o");
|
|
141
|
-
await browser.keys(",");
|
|
142
|
-
await browser.keys(" ");
|
|
143
|
-
await browser.keys("w");
|
|
144
|
-
await browser.keys("o");
|
|
145
|
-
await browser.keys("r");
|
|
146
|
-
await browser.keys("l");
|
|
147
|
-
await browser.keys("d");
|
|
148
|
-
await browser.keys("!");
|
|
149
|
-
expect(outerEditorState.doc.textContent).toBe("Hello, world!");
|
|
198
|
+
await user.type(editor, "Hello, world!");
|
|
199
|
+
expect(allStatesMatched).toBe(true);
|
|
150
200
|
});
|
|
151
201
|
it("supports React NodeViews", async ()=>{
|
|
152
202
|
const schema = new _prosemirrorModel.Schema({
|
|
153
203
|
nodes: {
|
|
154
204
|
text: {},
|
|
155
205
|
paragraph: {
|
|
156
|
-
content: "text*"
|
|
157
|
-
toDOM () {
|
|
158
|
-
return [
|
|
159
|
-
"p",
|
|
160
|
-
0
|
|
161
|
-
];
|
|
162
|
-
}
|
|
206
|
+
content: "text*"
|
|
163
207
|
},
|
|
164
208
|
doc: {
|
|
165
209
|
content: "paragraph+"
|
|
166
210
|
}
|
|
167
211
|
}
|
|
168
212
|
});
|
|
169
|
-
const
|
|
170
|
-
schema
|
|
213
|
+
const defaultState = _prosemirrorState.EditorState.create({
|
|
214
|
+
schema,
|
|
215
|
+
plugins: [
|
|
216
|
+
(0, _reactJs.react)()
|
|
217
|
+
]
|
|
171
218
|
});
|
|
172
|
-
|
|
219
|
+
function Paragraph(param) {
|
|
173
220
|
let { children } = param;
|
|
174
221
|
return /*#__PURE__*/ _react1.default.createElement("p", {
|
|
175
|
-
ref: ref,
|
|
176
222
|
"data-testid": "paragraph"
|
|
177
223
|
}, children);
|
|
178
|
-
}
|
|
179
|
-
const
|
|
180
|
-
paragraph:
|
|
224
|
+
}
|
|
225
|
+
const nodeViews = {
|
|
226
|
+
paragraph: ()=>({
|
|
227
|
+
component: Paragraph,
|
|
228
|
+
dom: document.createElement("div"),
|
|
229
|
+
contentDOM: document.createElement("span")
|
|
230
|
+
})
|
|
181
231
|
};
|
|
182
232
|
function TestEditor() {
|
|
233
|
+
const [mount, setMount] = (0, _react1.useState)(null);
|
|
183
234
|
return /*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
235
|
+
mount: mount,
|
|
236
|
+
defaultState: defaultState,
|
|
237
|
+
nodeViews: nodeViews
|
|
238
|
+
}, /*#__PURE__*/ _react1.default.createElement("div", {
|
|
239
|
+
"data-testid": "editor",
|
|
240
|
+
ref: setMount
|
|
188
241
|
}));
|
|
189
242
|
}
|
|
243
|
+
const user = _userEvent.default.setup();
|
|
190
244
|
(0, _react.render)(/*#__PURE__*/ _react1.default.createElement(TestEditor, null));
|
|
191
245
|
const editor = _react.screen.getByTestId("editor");
|
|
192
|
-
|
|
193
|
-
await browser.keys("H");
|
|
194
|
-
await browser.keys("e");
|
|
195
|
-
await browser.keys("l");
|
|
196
|
-
await browser.keys("l");
|
|
197
|
-
await browser.keys("o");
|
|
198
|
-
await browser.keys(",");
|
|
199
|
-
await browser.keys(" ");
|
|
200
|
-
await browser.keys("w");
|
|
201
|
-
await browser.keys("o");
|
|
202
|
-
await browser.keys("r");
|
|
203
|
-
await browser.keys("l");
|
|
204
|
-
await browser.keys("d");
|
|
205
|
-
await browser.keys("!");
|
|
246
|
+
await user.type(editor, "Hello, world!");
|
|
206
247
|
expect(editor.textContent).toBe("Hello, world!");
|
|
207
248
|
// Ensure that ProseMirror really rendered our Paragraph
|
|
208
249
|
// component, not just any old <p> tag
|
|
209
250
|
expect(_react.screen.getAllByTestId("paragraph").length).toBeGreaterThanOrEqual(1);
|
|
210
251
|
});
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)())
|
|
214
|
-
});
|
|
215
|
-
expect(view.state).toBe(view.props.state);
|
|
216
|
-
});
|
|
217
|
-
it("calls handleScrollToSelection when appropriate", async ()=>{
|
|
218
|
-
let scrolled = 0;
|
|
219
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
220
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)()),
|
|
221
|
-
handleScrollToSelection: ()=>{
|
|
222
|
-
scrolled++;
|
|
223
|
-
return false;
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
view.dispatch(view.state.tr.scrollIntoView());
|
|
227
|
-
expect(scrolled).toBe(1);
|
|
228
|
-
});
|
|
229
|
-
it("can be queried for the DOM position at a doc position", async ()=>{
|
|
230
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
231
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.ul)((0, _prosemirrorTestBuilder.li)((0, _prosemirrorTestBuilder.p)((0, _prosemirrorTestBuilder.strong)("foo")))))
|
|
232
|
-
});
|
|
233
|
-
const inText = view.domAtPos(4);
|
|
234
|
-
expect(inText.offset).toBe(1);
|
|
235
|
-
expect(inText.node.nodeValue).toBe("foo");
|
|
236
|
-
const beforeLI = view.domAtPos(1);
|
|
237
|
-
expect(beforeLI.offset).toBe(0);
|
|
238
|
-
expect(beforeLI.node.nodeName).toBe("UL");
|
|
239
|
-
const afterP = view.domAtPos(7);
|
|
240
|
-
expect(afterP.offset).toBe(1);
|
|
241
|
-
expect(afterP.node.nodeName).toBe("LI");
|
|
242
|
-
});
|
|
243
|
-
it("can bias DOM position queries to enter nodes", async ()=>{
|
|
244
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
245
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)((0, _prosemirrorTestBuilder.em)((0, _prosemirrorTestBuilder.strong)("a"), "b"), "c"))
|
|
246
|
-
});
|
|
247
|
-
function get(pos, bias) {
|
|
248
|
-
const r = view.domAtPos(pos, bias);
|
|
249
|
-
return (r.node.nodeType == 1 ? r.node.nodeName : r.node.nodeValue) + "@" + r.offset;
|
|
250
|
-
}
|
|
251
|
-
expect(get(1, 0)).toBe("P@0");
|
|
252
|
-
expect(get(1, -1)).toBe("P@0");
|
|
253
|
-
expect(get(1, 1)).toBe("a@0");
|
|
254
|
-
expect(get(2, -1)).toBe("a@1");
|
|
255
|
-
expect(get(2, 0)).toBe("EM@1");
|
|
256
|
-
expect(get(2, 1)).toBe("b@0");
|
|
257
|
-
expect(get(3, -1)).toBe("b@1");
|
|
258
|
-
expect(get(3, 0)).toBe("P@1");
|
|
259
|
-
expect(get(3, 1)).toBe("c@0");
|
|
260
|
-
expect(get(4, -1)).toBe("c@1");
|
|
261
|
-
expect(get(4, 0)).toBe("P@2");
|
|
262
|
-
expect(get(4, 1)).toBe("P@2");
|
|
263
|
-
});
|
|
264
|
-
it("can be queried for a node's DOM representation", async ()=>{
|
|
265
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
266
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)("foo"), (0, _prosemirrorTestBuilder.hr)())
|
|
267
|
-
});
|
|
268
|
-
expect(view.nodeDOM(0).nodeName).toBe("P");
|
|
269
|
-
expect(view.nodeDOM(5).nodeName).toBe("HR");
|
|
270
|
-
expect(view.nodeDOM(3)).toBeNull();
|
|
271
|
-
});
|
|
272
|
-
it("can map DOM positions to doc positions", async ()=>{
|
|
273
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
274
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)("foo"), (0, _prosemirrorTestBuilder.hr)())
|
|
275
|
-
});
|
|
276
|
-
expect(view.posAtDOM(view.dom.firstChild.firstChild, 2)).toBe(3);
|
|
277
|
-
expect(view.posAtDOM(view.dom, 1)).toBe(5);
|
|
278
|
-
expect(view.posAtDOM(view.dom, 2)).toBe(6);
|
|
279
|
-
expect(view.posAtDOM(view.dom.lastChild, 0, -1)).toBe(5);
|
|
280
|
-
expect(view.posAtDOM(view.dom.lastChild, 0, 1)).toBe(6);
|
|
281
|
-
});
|
|
282
|
-
it("binds this to itself in dispatchTransaction prop", async ()=>{
|
|
283
|
-
let thisBinding;
|
|
284
|
-
const { view } = (0, _editorViewTestHelpersJs.tempEditor)({
|
|
285
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)("foo"), (0, _prosemirrorTestBuilder.hr)()),
|
|
286
|
-
dispatchTransaction () {
|
|
287
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
288
|
-
thisBinding = this;
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
view.dispatch(view.state.tr.insertText("x"));
|
|
292
|
-
expect(view).toBe(thisBinding);
|
|
293
|
-
});
|
|
294
|
-
it("replaces the EditorView when ProseMirror would redraw", async ()=>{
|
|
295
|
-
const viewPlugin = ()=>new _prosemirrorState.Plugin({
|
|
296
|
-
props: {
|
|
297
|
-
nodeViews: {
|
|
298
|
-
horizontal_rule () {
|
|
299
|
-
const dom = document.createElement("hr");
|
|
300
|
-
return {
|
|
301
|
-
dom
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
});
|
|
307
|
-
const startDoc = (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.p)());
|
|
308
|
-
const firstState = _prosemirrorState.EditorState.create({
|
|
309
|
-
doc: startDoc,
|
|
310
|
-
schema: _prosemirrorTestBuilder.schema,
|
|
311
|
-
plugins: [
|
|
312
|
-
viewPlugin(),
|
|
313
|
-
(0, _reactKeysJs.reactKeys)()
|
|
314
|
-
]
|
|
315
|
-
});
|
|
316
|
-
let firstView = null;
|
|
317
|
-
let secondView = null;
|
|
318
|
-
function Test() {
|
|
319
|
-
(0, _useEditorEffectJs.useEditorEffect)((v)=>{
|
|
320
|
-
if (firstView === null) {
|
|
321
|
-
firstView = v;
|
|
322
|
-
} else {
|
|
323
|
-
secondView = v;
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
return null;
|
|
327
|
-
}
|
|
328
|
-
const Paragraph = /*#__PURE__*/ (0, _react1.forwardRef)(function Paragraph(param, ref) {
|
|
329
|
-
let { nodeProps , children , ...props } = param;
|
|
330
|
-
return /*#__PURE__*/ _react1.default.createElement("p", _extends({
|
|
331
|
-
ref: ref,
|
|
332
|
-
"data-testid": "node-view"
|
|
333
|
-
}, props), children);
|
|
334
|
-
});
|
|
335
|
-
const { rerender } = (0, _react.render)(/*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
336
|
-
state: firstState,
|
|
337
|
-
nodeViews: {
|
|
338
|
-
paragraph: Paragraph
|
|
339
|
-
}
|
|
340
|
-
}, /*#__PURE__*/ _react1.default.createElement(Test, null), /*#__PURE__*/ _react1.default.createElement(_proseMirrorDocJs.ProseMirrorDoc, null)));
|
|
341
|
-
expect(()=>_react.screen.getByTestId("node-view")).not.toThrow();
|
|
342
|
-
const secondState = _prosemirrorState.EditorState.create({
|
|
343
|
-
doc: startDoc,
|
|
344
|
-
schema: _prosemirrorTestBuilder.schema,
|
|
345
|
-
plugins: [
|
|
346
|
-
viewPlugin(),
|
|
347
|
-
(0, _reactKeysJs.reactKeys)()
|
|
348
|
-
]
|
|
349
|
-
});
|
|
350
|
-
rerender(/*#__PURE__*/ _react1.default.createElement(_proseMirrorJs.ProseMirror, {
|
|
351
|
-
state: secondState,
|
|
352
|
-
nodeViews: {
|
|
353
|
-
paragraph: Paragraph
|
|
354
|
-
}
|
|
355
|
-
}, /*#__PURE__*/ _react1.default.createElement(Test, null), /*#__PURE__*/ _react1.default.createElement(_proseMirrorDocJs.ProseMirrorDoc, null)));
|
|
356
|
-
expect(()=>_react.screen.getByTestId("node-view")).not.toThrow();
|
|
357
|
-
expect(firstView).not.toBeNull();
|
|
358
|
-
expect(secondView).not.toBeNull();
|
|
359
|
-
expect(firstView === secondView).toBeFalsy();
|
|
360
|
-
});
|
|
361
|
-
it("supports focusing interactive controls", async ()=>{
|
|
362
|
-
(0, _editorViewTestHelpersJs.tempEditor)({
|
|
363
|
-
doc: (0, _prosemirrorTestBuilder.doc)((0, _prosemirrorTestBuilder.hr)()),
|
|
364
|
-
nodeViews: {
|
|
365
|
-
horizontal_rule: /*#__PURE__*/ (0, _react1.forwardRef)(function Button(param, ref) {
|
|
366
|
-
let { nodeProps , ...props } = param;
|
|
367
|
-
(0, _useStopEventJs.useStopEvent)(()=>{
|
|
368
|
-
return true;
|
|
369
|
-
});
|
|
370
|
-
return /*#__PURE__*/ _react1.default.createElement("button", _extends({
|
|
371
|
-
id: "button",
|
|
372
|
-
ref: ref,
|
|
373
|
-
type: "button"
|
|
374
|
-
}, props), "Click me");
|
|
375
|
-
})
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
const button = _react.screen.getByText("Click me");
|
|
379
|
-
await $("#button").click();
|
|
380
|
-
expect(document.activeElement === button).toBeTruthy();
|
|
252
|
+
afterAll(()=>{
|
|
253
|
+
(0, _setupProseMirrorViewJs.teardownProseMirrorView)();
|
|
381
254
|
});
|
|
382
255
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "NodeViewsContext", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: ()=>NodeViewsContext
|
|
8
|
+
});
|
|
9
|
+
const _react = require("react");
|
|
10
|
+
const NodeViewsContext = (0, _react.createContext)(null);
|