@handlewithcare/react-prosemirror 3.1.1 → 3.1.3
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 +10 -0
- package/dist/cjs/components/ChildNodeViews.js +7 -5
- package/dist/cjs/hooks/useIsComposingIn.js +25 -0
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/plugins/beforeInputPlugin.js +13 -1
- package/dist/esm/components/ChildNodeViews.js +7 -5
- package/dist/esm/hooks/useIsComposingIn.js +17 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/plugins/beforeInputPlugin.js +13 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/components/__tests__/ProseMirror.memory-leak.test.d.ts +6 -0
- package/dist/types/hooks/useIsComposingIn.d.ts +4 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/tiptap/README.md +341 -0
package/README.md
CHANGED
|
@@ -90,6 +90,7 @@ import "prosemirror-view/style/prosemirror.css";
|
|
|
90
90
|
- [`useIgnoreMutation`](#useignoremutation)
|
|
91
91
|
- [`useSelectNode`](#useselectnode)
|
|
92
92
|
- [`useIsNodeSelected`](#useisnodeselected)
|
|
93
|
+
- [`useIsComposingIn`](#useiscomposingin)
|
|
93
94
|
- [`widget`](#widget)
|
|
94
95
|
- [`reorderSiblings`](#reordersiblings)
|
|
95
96
|
- [When should I use this?](#when-should-i-use-this)
|
|
@@ -764,6 +765,15 @@ This hook can be used within a node view component to subscribe to a boolean
|
|
|
764
765
|
value determining whether this node is selected. The hook will return true when
|
|
765
766
|
a NodeSelection is created whose node is this one.
|
|
766
767
|
|
|
768
|
+
### `useIsComposingIn`
|
|
769
|
+
|
|
770
|
+
```tsx
|
|
771
|
+
type useIsComposingIn = (): boolean
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
This hook can be used within a node view component to subscribe to a boolean
|
|
775
|
+
value determining whether an IME composition is active inside the node.
|
|
776
|
+
|
|
767
777
|
### `widget`
|
|
768
778
|
|
|
769
779
|
```ts
|
|
@@ -20,7 +20,7 @@ const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
|
|
|
20
20
|
const _ChildDescriptionsContext = require("../contexts/ChildDescriptionsContext.js");
|
|
21
21
|
const _EditorContext = require("../contexts/EditorContext.js");
|
|
22
22
|
const _iterDeco = require("../decorations/iterDeco.js");
|
|
23
|
-
const
|
|
23
|
+
const _reactKeys = require("../plugins/reactKeys.js");
|
|
24
24
|
const _props = require("../props.js");
|
|
25
25
|
const _viewdesc = require("../viewdesc.js");
|
|
26
26
|
const _NativeWidgetView = require("./NativeWidgetView.js");
|
|
@@ -305,7 +305,7 @@ function createChildElements(children, getInnerPos) {
|
|
|
305
305
|
}
|
|
306
306
|
const ChildNodeViews = /*#__PURE__*/ (0, _react.memo)(function ChildNodeViews(param) {
|
|
307
307
|
let { getPos, node, innerDecorations } = param;
|
|
308
|
-
const
|
|
308
|
+
const { view } = (0, _react.useContext)(_EditorContext.EditorContext);
|
|
309
309
|
const getInnerPos = (0, _react.useCallback)(()=>getPos() + 1, [
|
|
310
310
|
getPos
|
|
311
311
|
]);
|
|
@@ -315,11 +315,12 @@ const ChildNodeViews = /*#__PURE__*/ (0, _react.memo)(function ChildNodeViews(pa
|
|
|
315
315
|
let widgetChildren = [];
|
|
316
316
|
let lastNodeChild = null;
|
|
317
317
|
(0, _iterDeco.iterDeco)(node, innerDecorations, (widget, isNative, offset, index)=>{
|
|
318
|
+
const posToKey = _reactKeys.reactKeysPluginKey.getState(view.state)?.posToKey;
|
|
318
319
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
319
320
|
const widgetMarks = widget.type.spec.marks ?? [];
|
|
320
321
|
let key;
|
|
321
322
|
if (isNative) {
|
|
322
|
-
key = createKey(getInnerPos(), offset, index, "native-widget",
|
|
323
|
+
key = createKey(getInnerPos(), offset, index, "native-widget", posToKey, widget);
|
|
323
324
|
const child = {
|
|
324
325
|
type: "native-widget",
|
|
325
326
|
widget,
|
|
@@ -336,7 +337,7 @@ const ChildNodeViews = /*#__PURE__*/ (0, _react.memo)(function ChildNodeViews(pa
|
|
|
336
337
|
}
|
|
337
338
|
keysSeen.set(key, keysSeen.size);
|
|
338
339
|
} else {
|
|
339
|
-
key = createKey(getInnerPos(), offset, index, "widget",
|
|
340
|
+
key = createKey(getInnerPos(), offset, index, "widget", posToKey, widget);
|
|
340
341
|
const child = {
|
|
341
342
|
type: "widget",
|
|
342
343
|
widget: widget,
|
|
@@ -357,7 +358,8 @@ const ChildNodeViews = /*#__PURE__*/ (0, _react.memo)(function ChildNodeViews(pa
|
|
|
357
358
|
widgetChildren.push(child);
|
|
358
359
|
adjustWidgetMarksForward(lastNodeChild, childMap.get(key));
|
|
359
360
|
}, (childNode, outerDeco, innerDeco, offset, index)=>{
|
|
360
|
-
const
|
|
361
|
+
const posToKey = _reactKeys.reactKeysPluginKey.getState(view.state)?.posToKey;
|
|
362
|
+
const key = createKey(getInnerPos(), offset, index, "node", posToKey);
|
|
361
363
|
const child = {
|
|
362
364
|
type: "node",
|
|
363
365
|
node: childNode,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "useIsComposingIn", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return useIsComposingIn;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = require("react");
|
|
12
|
+
const _NodeView = require("../components/nodes/NodeView.js");
|
|
13
|
+
const _index = require("../index.js");
|
|
14
|
+
function useIsComposingIn() {
|
|
15
|
+
const [isComposing, setIsComposing] = (0, _react.useState)(false);
|
|
16
|
+
const getPos = (0, _react.useContext)(_NodeView.GetPosContext);
|
|
17
|
+
(0, _index.useEditorEventListener)("compositionstart", (view)=>{
|
|
18
|
+
const compositionRoot = view.state.selection.$from.before();
|
|
19
|
+
setIsComposing(compositionRoot === getPos());
|
|
20
|
+
});
|
|
21
|
+
(0, _index.useEditorEventListener)("compositionend", ()=>{
|
|
22
|
+
setIsComposing(false);
|
|
23
|
+
});
|
|
24
|
+
return isComposing;
|
|
25
|
+
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -37,6 +37,9 @@ _export(exports, {
|
|
|
37
37
|
useIgnoreMutation: function() {
|
|
38
38
|
return _useIgnoreMutation.useIgnoreMutation;
|
|
39
39
|
},
|
|
40
|
+
useIsComposingIn: function() {
|
|
41
|
+
return _useIsComposingIn.useIsComposingIn;
|
|
42
|
+
},
|
|
40
43
|
useIsEditorStatic: function() {
|
|
41
44
|
return _useIsEditorStatic.useIsEditorStatic;
|
|
42
45
|
},
|
|
@@ -62,6 +65,7 @@ _export(exports, {
|
|
|
62
65
|
const _ProseMirror = require("./components/ProseMirror.js");
|
|
63
66
|
const _ProseMirrorDoc = require("./components/ProseMirrorDoc.js");
|
|
64
67
|
const _reorderSiblings = require("./commands/reorderSiblings.js");
|
|
68
|
+
const _useIsComposingIn = require("./hooks/useIsComposingIn.js");
|
|
65
69
|
const _useEditorEffect = require("./hooks/useEditorEffect.js");
|
|
66
70
|
const _useEditorEventCallback = require("./hooks/useEditorEventCallback.js");
|
|
67
71
|
const _useEditorEventListener = require("./hooks/useEditorEventListener.js");
|
|
@@ -219,7 +219,19 @@ function beforeInputPlugin() {
|
|
|
219
219
|
}
|
|
220
220
|
case "insertText":
|
|
221
221
|
{
|
|
222
|
-
|
|
222
|
+
const ranges = event.getTargetRanges();
|
|
223
|
+
if (ranges.length === 0 || ranges.length === 1 && ranges[0] && ranges[0].collapsed) {
|
|
224
|
+
insertText(view, event.data);
|
|
225
|
+
} else {
|
|
226
|
+
for (const range of ranges){
|
|
227
|
+
const from = view.posAtDOM(range.startContainer, range.startOffset, 1);
|
|
228
|
+
const to = view.posAtDOM(range.endContainer, range.endOffset, 1);
|
|
229
|
+
insertText(view, event.data, {
|
|
230
|
+
from,
|
|
231
|
+
to
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}
|
|
223
235
|
break;
|
|
224
236
|
}
|
|
225
237
|
case "deleteWordBackward":
|
|
@@ -2,7 +2,7 @@ import React, { cloneElement, createElement, memo, useCallback, useContext, useR
|
|
|
2
2
|
import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js";
|
|
3
3
|
import { EditorContext } from "../contexts/EditorContext.js";
|
|
4
4
|
import { iterDeco } from "../decorations/iterDeco.js";
|
|
5
|
-
import {
|
|
5
|
+
import { reactKeysPluginKey } from "../plugins/reactKeys.js";
|
|
6
6
|
import { htmlAttrsToReactProps, mergeReactProps } from "../props.js";
|
|
7
7
|
import { sameOuterDeco } from "../viewdesc.js";
|
|
8
8
|
import { NativeWidgetView } from "./NativeWidgetView.js";
|
|
@@ -246,7 +246,7 @@ function createChildElements(children, getInnerPos) {
|
|
|
246
246
|
}
|
|
247
247
|
export const ChildNodeViews = /*#__PURE__*/ memo(function ChildNodeViews(param) {
|
|
248
248
|
let { getPos, node, innerDecorations } = param;
|
|
249
|
-
const
|
|
249
|
+
const { view } = useContext(EditorContext);
|
|
250
250
|
const getInnerPos = useCallback(()=>getPos() + 1, [
|
|
251
251
|
getPos
|
|
252
252
|
]);
|
|
@@ -256,11 +256,12 @@ export const ChildNodeViews = /*#__PURE__*/ memo(function ChildNodeViews(param)
|
|
|
256
256
|
let widgetChildren = [];
|
|
257
257
|
let lastNodeChild = null;
|
|
258
258
|
iterDeco(node, innerDecorations, (widget, isNative, offset, index)=>{
|
|
259
|
+
const posToKey = reactKeysPluginKey.getState(view.state)?.posToKey;
|
|
259
260
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
260
261
|
const widgetMarks = widget.type.spec.marks ?? [];
|
|
261
262
|
let key;
|
|
262
263
|
if (isNative) {
|
|
263
|
-
key = createKey(getInnerPos(), offset, index, "native-widget",
|
|
264
|
+
key = createKey(getInnerPos(), offset, index, "native-widget", posToKey, widget);
|
|
264
265
|
const child = {
|
|
265
266
|
type: "native-widget",
|
|
266
267
|
widget,
|
|
@@ -277,7 +278,7 @@ export const ChildNodeViews = /*#__PURE__*/ memo(function ChildNodeViews(param)
|
|
|
277
278
|
}
|
|
278
279
|
keysSeen.set(key, keysSeen.size);
|
|
279
280
|
} else {
|
|
280
|
-
key = createKey(getInnerPos(), offset, index, "widget",
|
|
281
|
+
key = createKey(getInnerPos(), offset, index, "widget", posToKey, widget);
|
|
281
282
|
const child = {
|
|
282
283
|
type: "widget",
|
|
283
284
|
widget: widget,
|
|
@@ -298,7 +299,8 @@ export const ChildNodeViews = /*#__PURE__*/ memo(function ChildNodeViews(param)
|
|
|
298
299
|
widgetChildren.push(child);
|
|
299
300
|
adjustWidgetMarksForward(lastNodeChild, childMap.get(key));
|
|
300
301
|
}, (childNode, outerDeco, innerDeco, offset, index)=>{
|
|
301
|
-
const
|
|
302
|
+
const posToKey = reactKeysPluginKey.getState(view.state)?.posToKey;
|
|
303
|
+
const key = createKey(getInnerPos(), offset, index, "node", posToKey);
|
|
302
304
|
const child = {
|
|
303
305
|
type: "node",
|
|
304
306
|
node: childNode,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useContext, useState } from "react";
|
|
2
|
+
import { GetPosContext } from "../components/nodes/NodeView.js";
|
|
3
|
+
import { useEditorEventListener } from "../index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Returns true while an IME composition is active inside the current node.
|
|
6
|
+
*/ export function useIsComposingIn() {
|
|
7
|
+
const [isComposing, setIsComposing] = useState(false);
|
|
8
|
+
const getPos = useContext(GetPosContext);
|
|
9
|
+
useEditorEventListener("compositionstart", (view)=>{
|
|
10
|
+
const compositionRoot = view.state.selection.$from.before();
|
|
11
|
+
setIsComposing(compositionRoot === getPos());
|
|
12
|
+
});
|
|
13
|
+
useEditorEventListener("compositionend", ()=>{
|
|
14
|
+
setIsComposing(false);
|
|
15
|
+
});
|
|
16
|
+
return isComposing;
|
|
17
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export { ProseMirror } from "./components/ProseMirror.js";
|
|
3
3
|
export { ProseMirrorDoc } from "./components/ProseMirrorDoc.js";
|
|
4
4
|
export { reorderSiblings } from "./commands/reorderSiblings.js";
|
|
5
|
+
export { useIsComposingIn } from "./hooks/useIsComposingIn.js";
|
|
5
6
|
export { useEditorEffect } from "./hooks/useEditorEffect.js";
|
|
6
7
|
export { useEditorEventCallback } from "./hooks/useEditorEventCallback.js";
|
|
7
8
|
export { useEditorEventListener } from "./hooks/useEditorEventListener.js";
|
|
@@ -209,7 +209,19 @@ export function beforeInputPlugin() {
|
|
|
209
209
|
}
|
|
210
210
|
case "insertText":
|
|
211
211
|
{
|
|
212
|
-
|
|
212
|
+
const ranges = event.getTargetRanges();
|
|
213
|
+
if (ranges.length === 0 || ranges.length === 1 && ranges[0] && ranges[0].collapsed) {
|
|
214
|
+
insertText(view, event.data);
|
|
215
|
+
} else {
|
|
216
|
+
for (const range of ranges){
|
|
217
|
+
const from = view.posAtDOM(range.startContainer, range.startOffset, 1);
|
|
218
|
+
const to = view.posAtDOM(range.endContainer, range.endOffset, 1);
|
|
219
|
+
insertText(view, event.data, {
|
|
220
|
+
from,
|
|
221
|
+
to
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
213
225
|
break;
|
|
214
226
|
}
|
|
215
227
|
case "deleteWordBackward":
|