@handlewithcare/react-prosemirror 2.2.4 → 2.3.1
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 +13 -2
- package/dist/cjs/components/CustomNodeView.js +68 -29
- package/dist/cjs/components/ReactNodeView.js +5 -2
- package/dist/cjs/contexts/IgnoreMutationContext.js +12 -0
- package/dist/cjs/hooks/useClientOnly.js +6 -5
- package/dist/cjs/hooks/useEditor.js +1 -1
- package/dist/cjs/hooks/useEditorEventCallback.js +6 -4
- package/dist/cjs/hooks/useIgnoreMutation.js +24 -0
- package/dist/cjs/hooks/useNodeViewDescriptor.js +7 -2
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/props.js +36 -25
- package/dist/cjs/viewdesc.js +6 -6
- package/dist/esm/components/CustomNodeView.js +68 -29
- package/dist/esm/components/ReactNodeView.js +5 -2
- package/dist/esm/contexts/IgnoreMutationContext.js +2 -0
- package/dist/esm/hooks/useClientOnly.js +7 -6
- package/dist/esm/hooks/useEditor.js +1 -1
- package/dist/esm/hooks/useEditorEventCallback.js +6 -4
- package/dist/esm/hooks/useIgnoreMutation.js +14 -0
- package/dist/esm/hooks/useNodeViewDescriptor.js +7 -2
- package/dist/esm/index.js +1 -0
- package/dist/esm/props.js +36 -23
- package/dist/esm/viewdesc.js +6 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/components/NodeViewComponentProps.d.ts +2 -1
- package/dist/types/components/ProseMirror.d.ts +2 -2
- package/dist/types/contexts/IgnoreMutationContext.d.ts +4 -0
- package/dist/types/contexts/NodeViewContext.d.ts +2 -2
- package/dist/types/hooks/useEditorEventCallback.d.ts +1 -1
- package/dist/types/hooks/useIgnoreMutation.d.ts +2 -0
- package/dist/types/hooks/useNodeViewDescriptor.d.ts +2 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/props.d.ts +1 -7
- package/dist/types/viewdesc.d.ts +2 -2
- package/package.json +1 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { cloneElement, memo, useContext, useMemo, useRef } from "react";
|
|
2
2
|
import { ChildDescriptorsContext } from "../contexts/ChildDescriptorsContext.js";
|
|
3
|
+
import { IgnoreMutationContext } from "../contexts/IgnoreMutationContext.js";
|
|
3
4
|
import { NodeViewContext } from "../contexts/NodeViewContext.js";
|
|
4
5
|
import { SelectNodeContext } from "../contexts/SelectNodeContext.js";
|
|
5
6
|
import { StopEventContext } from "../contexts/StopEventContext.js";
|
|
@@ -18,7 +19,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
18
19
|
const outputSpec = useMemo(()=>node.type.spec.toDOM?.(node), [
|
|
19
20
|
node
|
|
20
21
|
]);
|
|
21
|
-
const { hasContentDOM, childDescriptors, setStopEvent, setSelectNode, nodeViewDescRef } = useNodeViewDescriptor(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
|
|
22
|
+
const { hasContentDOM, childDescriptors, setStopEvent, setSelectNode, setIgnoreMutation, nodeViewDescRef } = useNodeViewDescriptor(node, ()=>getPos.current(), domRef, nodeDomRef, innerDeco, outerDeco, undefined, contentDomRef);
|
|
22
23
|
const finalProps = {
|
|
23
24
|
...props,
|
|
24
25
|
...!hasContentDOM && {
|
|
@@ -79,7 +80,9 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
79
80
|
value: setSelectNode
|
|
80
81
|
}, /*#__PURE__*/ React.createElement(StopEventContext.Provider, {
|
|
81
82
|
value: setStopEvent
|
|
83
|
+
}, /*#__PURE__*/ React.createElement(IgnoreMutationContext.Provider, {
|
|
84
|
+
value: setIgnoreMutation
|
|
82
85
|
}, /*#__PURE__*/ React.createElement(ChildDescriptorsContext.Provider, {
|
|
83
86
|
value: childContextValue
|
|
84
|
-
}, decoratedElement)));
|
|
87
|
+
}, decoratedElement))));
|
|
85
88
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
3
|
+
function unsubscribe() {}
|
|
4
|
+
function subscribe() {
|
|
5
|
+
return unsubscribe;
|
|
6
|
+
}
|
|
2
7
|
export function useClientOnly() {
|
|
3
|
-
|
|
4
|
-
useEffect(()=>{
|
|
5
|
-
setRender(true);
|
|
6
|
-
}, []);
|
|
7
|
-
return render;
|
|
8
|
+
return useSyncExternalStore(subscribe, ()=>true, ()=>false);
|
|
8
9
|
}
|
|
@@ -220,7 +220,7 @@ let didWarnValueDefaultValue = false;
|
|
|
220
220
|
cleanup();
|
|
221
221
|
const docViewDescRef = useRef(new NodeViewDesc(undefined, [], ()=>-1, state.doc, [], DecorationSet.empty, tempDom, null, tempDom, ()=>false, ()=>{
|
|
222
222
|
/* The doc node can't have a node selection*/ }, ()=>{
|
|
223
|
-
/* The doc node can't have a node selection*/ }));
|
|
223
|
+
/* The doc node can't have a node selection*/ }, ()=>false));
|
|
224
224
|
const directEditorProps = {
|
|
225
225
|
...options,
|
|
226
226
|
state,
|
|
@@ -25,10 +25,12 @@ import { useEditorEffect } from "./useEditorEffect.js";
|
|
|
25
25
|
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
26
26
|
args[_key] = arguments[_key];
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
// It's not actually possible for an event handler to run
|
|
29
|
+
// while view is null, since view is only ever set to
|
|
30
|
+
// null in a layout effect that then immediately triggers
|
|
31
|
+
// a re-render which sets view to a new EditorView
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
33
|
+
return ref.current(view, ...args);
|
|
32
34
|
}, [
|
|
33
35
|
view
|
|
34
36
|
]);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { IgnoreMutationContext } from "../contexts/IgnoreMutationContext.js";
|
|
3
|
+
import { useEditorEffect } from "./useEditorEffect.js";
|
|
4
|
+
import { useEditorEventCallback } from "./useEditorEventCallback.js";
|
|
5
|
+
export function useIgnoreMutation(ignoreMutation) {
|
|
6
|
+
const register = useContext(IgnoreMutationContext);
|
|
7
|
+
const ignoreMutationMemo = useEditorEventCallback(ignoreMutation);
|
|
8
|
+
useEditorEffect(()=>{
|
|
9
|
+
register(ignoreMutationMemo);
|
|
10
|
+
}, [
|
|
11
|
+
register,
|
|
12
|
+
ignoreMutationMemo
|
|
13
|
+
]);
|
|
14
|
+
}
|
|
@@ -11,6 +11,10 @@ export function useNodeViewDescriptor(node, getPos, domRef, nodeDomRef, innerDec
|
|
|
11
11
|
const setStopEvent = useCallback((newStopEvent)=>{
|
|
12
12
|
stopEvent.current = newStopEvent;
|
|
13
13
|
}, []);
|
|
14
|
+
const ignoreMutation = useRef(()=>false);
|
|
15
|
+
const setIgnoreMutation = useCallback((newIgnoreMutation)=>{
|
|
16
|
+
ignoreMutation.current = newIgnoreMutation;
|
|
17
|
+
}, []);
|
|
14
18
|
const selectNode = useRef(()=>{
|
|
15
19
|
if (!nodeDomRef.current || !node) return;
|
|
16
20
|
if (nodeDomRef.current.nodeType == 1) nodeDomRef.current.classList.add("ProseMirror-selectednode");
|
|
@@ -46,7 +50,7 @@ export function useNodeViewDescriptor(node, getPos, domRef, nodeDomRef, innerDec
|
|
|
46
50
|
if (!node || !nodeDomRef.current) return;
|
|
47
51
|
const firstChildDesc = childDescriptors.current[0];
|
|
48
52
|
if (!nodeViewDescRef.current) {
|
|
49
|
-
nodeViewDescRef.current = new NodeViewDesc(parentRef.current, childDescriptors.current, getPos, node, outerDecorations, innerDecorations, domRef?.current ?? nodeDomRef.current, firstChildDesc?.dom.parentElement ?? null, nodeDomRef.current, (event)=>!!stopEvent.current(event), ()=>selectNode.current(), ()=>deselectNode.current());
|
|
53
|
+
nodeViewDescRef.current = new NodeViewDesc(parentRef.current, childDescriptors.current, getPos, node, outerDecorations, innerDecorations, domRef?.current ?? nodeDomRef.current, firstChildDesc?.dom.parentElement ?? null, nodeDomRef.current, (event)=>!!stopEvent.current(event), ()=>selectNode.current(), ()=>deselectNode.current(), (mutation)=>ignoreMutation.current(mutation));
|
|
50
54
|
} else {
|
|
51
55
|
nodeViewDescRef.current.parent = parentRef.current;
|
|
52
56
|
nodeViewDescRef.current.children = childDescriptors.current;
|
|
@@ -101,6 +105,7 @@ export function useNodeViewDescriptor(node, getPos, domRef, nodeDomRef, innerDec
|
|
|
101
105
|
childDescriptors,
|
|
102
106
|
nodeViewDescRef,
|
|
103
107
|
setStopEvent,
|
|
104
|
-
setSelectNode
|
|
108
|
+
setSelectNode,
|
|
109
|
+
setIgnoreMutation
|
|
105
110
|
};
|
|
106
111
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { useEditorEventListener } from "./hooks/useEditorEventListener.js";
|
|
|
7
7
|
export { useEditorState } from "./hooks/useEditorState.js";
|
|
8
8
|
export { useStopEvent } from "./hooks/useStopEvent.js";
|
|
9
9
|
export { useSelectNode } from "./hooks/useSelectNode.js";
|
|
10
|
+
export { useIgnoreMutation } from "./hooks/useIgnoreMutation.js";
|
|
10
11
|
export { useIsNodeSelected } from "./hooks/useIsNodeSelected.js";
|
|
11
12
|
export { reactKeys } from "./plugins/reactKeys.js";
|
|
12
13
|
export { widget } from "./decorations/ReactWidgetType.js";
|
package/dist/esm/props.js
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import cx from "classnames";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
let patched = false;
|
|
3
|
+
function patchConsoleError() {
|
|
4
|
+
if (patched) return;
|
|
5
|
+
/* eslint-disable no-console */ const consoleError = console.error;
|
|
6
|
+
console.error = function() {
|
|
7
|
+
for(var _len = arguments.length, data = new Array(_len), _key = 0; _key < _len; _key++){
|
|
8
|
+
data[_key] = arguments[_key];
|
|
9
|
+
}
|
|
10
|
+
const [message, prop, correction] = data;
|
|
11
|
+
if (typeof message === "string" && message.startsWith("Warning: Invalid DOM property `%s`. Did you mean `%s`?") && prop === "STYLE" && correction === "style") {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
consoleError(...data);
|
|
15
|
+
};
|
|
16
|
+
patched = true;
|
|
17
|
+
/* eslint-enable no-console */ }
|
|
18
|
+
function mergeStyleProps(a, b) {
|
|
19
|
+
if (!("STYLE" in a)) {
|
|
20
|
+
if (!("STYLE" in b)) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
return b.STYLE;
|
|
24
|
+
}
|
|
25
|
+
if (!("STYLE" in b)) {
|
|
26
|
+
return a.STYLE;
|
|
23
27
|
}
|
|
24
|
-
return
|
|
28
|
+
return `${a.STYLE.match(/;\s*$/) ? a.STYLE : `${a.STYLE}`} ${b.STYLE}`;
|
|
25
29
|
}
|
|
26
30
|
/**
|
|
27
31
|
* Merges two sets of React props. Class names
|
|
@@ -32,6 +36,7 @@ export function kebabCaseToCamelCase(str) {
|
|
|
32
36
|
...a,
|
|
33
37
|
...b,
|
|
34
38
|
className: cx(a.className, b.className),
|
|
39
|
+
STYLE: mergeStyleProps(a, b),
|
|
35
40
|
style: {
|
|
36
41
|
...a.style,
|
|
37
42
|
...b.style
|
|
@@ -42,6 +47,7 @@ export function kebabCaseToCamelCase(str) {
|
|
|
42
47
|
* Given a record of HTML attributes, returns tho
|
|
43
48
|
* equivalent React props.
|
|
44
49
|
*/ export function htmlAttrsToReactProps(attrs) {
|
|
50
|
+
patchConsoleError();
|
|
45
51
|
const props = {};
|
|
46
52
|
for (const [attrName, attrValue] of Object.entries(attrs)){
|
|
47
53
|
switch(attrName.toLowerCase()){
|
|
@@ -52,7 +58,14 @@ export function kebabCaseToCamelCase(str) {
|
|
|
52
58
|
}
|
|
53
59
|
case "style":
|
|
54
60
|
{
|
|
55
|
-
|
|
61
|
+
// HACK: React expects the `style` prop to be an
|
|
62
|
+
// object mapping from CSS property name to value.
|
|
63
|
+
// However, it will pass un-recognized props through
|
|
64
|
+
// to the underlying DOM element, and HTML attributes
|
|
65
|
+
// are case insensitive. So we use `STYLE` instead,
|
|
66
|
+
// which React doesn't intercept, but the DOM treats
|
|
67
|
+
// as `style`
|
|
68
|
+
props.STYLE = attrValue;
|
|
56
69
|
break;
|
|
57
70
|
}
|
|
58
71
|
case "autocapitalize":
|
package/dist/esm/viewdesc.js
CHANGED
|
@@ -539,8 +539,9 @@ export class NodeViewDesc extends ViewDesc {
|
|
|
539
539
|
stopEvent;
|
|
540
540
|
selectNode;
|
|
541
541
|
deselectNode;
|
|
542
|
-
|
|
543
|
-
|
|
542
|
+
ignoreMutation;
|
|
543
|
+
constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, stopEvent, selectNode, deselectNode, ignoreMutation){
|
|
544
|
+
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;
|
|
544
545
|
}
|
|
545
546
|
updateOuterDeco() {
|
|
546
547
|
// pass
|
|
@@ -600,7 +601,9 @@ export class TextViewDesc extends NodeViewDesc {
|
|
|
600
601
|
constructor(parent, children, getPos, node, outerDeco, innerDeco, dom, nodeDOM){
|
|
601
602
|
super(parent, children, getPos, node, outerDeco, innerDeco, dom, null, nodeDOM, ()=>false, ()=>{
|
|
602
603
|
/* Text nodes can't have node selections */ }, ()=>{
|
|
603
|
-
/* Text nodes can't have node selections */ })
|
|
604
|
+
/* Text nodes can't have node selections */ }, (mutation)=>{
|
|
605
|
+
return mutation.type != "characterData" && mutation.type != "selection";
|
|
606
|
+
});
|
|
604
607
|
}
|
|
605
608
|
parseRule() {
|
|
606
609
|
let skip = this.nodeDOM.parentNode;
|
|
@@ -627,9 +630,6 @@ export class TextViewDesc extends NodeViewDesc {
|
|
|
627
630
|
if (dom == this.nodeDOM) return this.posAtStart + Math.min(offset, this.node.text.length);
|
|
628
631
|
return super.localPosFromDOM(dom, offset, bias);
|
|
629
632
|
}
|
|
630
|
-
ignoreMutation(mutation) {
|
|
631
|
-
return mutation.type != "characterData" && mutation.type != "selection";
|
|
632
|
-
}
|
|
633
633
|
markDirty(from, to) {
|
|
634
634
|
super.markDirty(from, to);
|
|
635
635
|
if (this.dom != this.nodeDOM && (from == 0 || to == this.nodeDOM.nodeValue.length)) this.dirty = NODE_DIRTY;
|