@handlewithcare/react-prosemirror 2.9.0-tiptap.24 → 3.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.
- package/README.md +140 -75
- package/dist/cjs/StaticEditorView.js +0 -3
- package/dist/cjs/components/ChildNodeViews.js +4 -4
- package/dist/cjs/components/NativeWidgetView.js +2 -2
- package/dist/cjs/components/OutputSpec.js +10 -3
- package/dist/cjs/components/ProseMirror.js +11 -17
- package/dist/cjs/components/SeparatorHackView.js +2 -2
- package/dist/cjs/components/TrailingHackView.js +2 -2
- package/dist/cjs/components/WidgetView.js +2 -2
- package/dist/cjs/components/marks/DefaultMarkView.js +2 -1
- package/dist/cjs/components/marks/MarkView.js +2 -2
- package/dist/cjs/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +16 -7
- package/dist/cjs/components/marks/ReactMarkView.js +26 -6
- package/dist/cjs/components/nodes/DefaultNodeView.js +3 -2
- package/dist/cjs/components/nodes/DocNodeView.js +7 -6
- package/dist/cjs/components/nodes/NodeView.js +17 -6
- package/dist/cjs/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +22 -9
- package/dist/cjs/components/nodes/ReactNodeView.js +59 -17
- package/dist/cjs/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +3 -3
- package/dist/cjs/hooks/useEditor.js +0 -4
- package/dist/cjs/hooks/useEditorEventCallback.js +1 -1
- package/dist/cjs/hooks/useMarkViewDescription.js +24 -21
- package/dist/cjs/hooks/useNodePos.js +18 -0
- package/dist/cjs/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +30 -25
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/refs.js +28 -0
- package/dist/cjs/viewdesc.js +18 -5
- package/dist/esm/StaticEditorView.js +0 -3
- package/dist/esm/components/ChildNodeViews.js +4 -4
- package/dist/esm/components/NativeWidgetView.js +2 -2
- package/dist/esm/components/OutputSpec.js +10 -3
- package/dist/esm/components/ProseMirror.js +11 -17
- package/dist/esm/components/SeparatorHackView.js +2 -2
- package/dist/esm/components/TrailingHackView.js +2 -2
- package/dist/esm/components/WidgetView.js +2 -2
- package/dist/esm/components/marks/DefaultMarkView.js +2 -1
- package/dist/esm/components/marks/MarkView.js +2 -2
- package/dist/esm/components/marks/{CustomMarkView.js → MarkViewConstructorView.js} +14 -5
- package/dist/esm/components/marks/ReactMarkView.js +26 -6
- package/dist/esm/components/nodes/DefaultNodeView.js +3 -2
- package/dist/esm/components/nodes/DocNodeView.js +8 -7
- package/dist/esm/components/nodes/NodeView.js +7 -4
- package/dist/esm/components/nodes/{CustomNodeView.js → NodeViewConstructorView.js} +20 -7
- package/dist/esm/components/nodes/ReactNodeView.js +59 -17
- package/dist/esm/contexts/{ChildDescriptorsContext.js → ChildDescriptionsContext.js} +1 -1
- package/dist/esm/hooks/useEditor.js +0 -4
- package/dist/esm/hooks/useEditorEffect.js +0 -4
- package/dist/esm/hooks/useEditorEventCallback.js +6 -4
- package/dist/esm/hooks/useMarkViewDescription.js +26 -23
- package/dist/esm/hooks/useNodePos.js +15 -0
- package/dist/esm/hooks/{useNodeViewDescriptor.js → useNodeViewDescription.js} +29 -24
- package/dist/esm/index.js +2 -0
- package/dist/esm/refs.js +18 -0
- package/dist/esm/viewdesc.js +13 -6
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/AbstractEditorView.d.ts +0 -1
- package/dist/types/StaticEditorView.d.ts +0 -1
- package/dist/types/components/OutputSpec.d.ts +2 -1
- package/dist/types/components/ProseMirror.d.ts +3 -11
- package/dist/types/components/ProseMirrorDoc.d.ts +2 -2
- package/dist/types/components/marks/DefaultMarkView.d.ts +1 -1
- package/dist/types/components/marks/MarkViewComponentProps.d.ts +4 -3
- package/dist/types/components/marks/{CustomMarkView.d.ts → MarkViewConstructorView.d.ts} +1 -1
- package/dist/types/components/nodes/DefaultNodeView.d.ts +1 -1
- package/dist/types/components/nodes/DocNodeView.d.ts +2 -2
- package/dist/types/components/nodes/NodeView.d.ts +1 -0
- package/dist/types/components/nodes/NodeViewComponentProps.d.ts +4 -3
- package/dist/types/components/{CustomNodeView.d.ts → nodes/NodeViewConstructorView.d.ts} +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/contexts/{ChildDescriptorsContext.d.ts → ChildDescriptionsContext.d.ts} +1 -1
- package/dist/types/hooks/useEditorEffect.d.ts +0 -4
- package/dist/types/hooks/useEditorEventCallback.d.ts +6 -4
- package/dist/types/hooks/useMarkViewDescription.d.ts +6 -9
- package/dist/types/hooks/useNodePos.d.ts +9 -0
- package/dist/types/hooks/{useNodeViewDescriptor.d.ts → useNodeViewDescription.d.ts} +5 -9
- package/dist/types/index.d.ts +2 -0
- package/dist/types/props.d.ts +26 -26
- package/dist/types/refs.d.ts +2 -0
- package/dist/types/viewdesc.d.ts +4 -0
- package/package.json +12 -20
- package/dist/cjs/components/CustomNodeView.js +0 -132
- package/dist/cjs/components/DefaultNodeView.js +0 -67
- package/dist/cjs/components/DocNodeView.js +0 -96
- package/dist/cjs/components/MarkView.js +0 -119
- package/dist/cjs/components/NodeView.js +0 -86
- package/dist/cjs/components/NodeViewComponentProps.js +0 -4
- package/dist/cjs/components/ReactNodeView.js +0 -174
- package/dist/cjs/components/marks/OldMarkView.js +0 -120
- package/dist/cjs/tiptap/ReactProseMirrorNodeView.js +0 -26
- package/dist/cjs/tiptap/TiptapEditor.js +0 -34
- package/dist/cjs/tiptap/TiptapEditorContent.js +0 -142
- package/dist/cjs/tiptap/TiptapEditorView.js +0 -118
- package/dist/cjs/tiptap/TiptapNodeView.js +0 -26
- package/dist/cjs/tiptap/contexts/TiptapEditorContext.js +0 -12
- package/dist/cjs/tiptap/extensions/ReactProseMirror.js +0 -40
- package/dist/cjs/tiptap/hooks/useIsInReactProseMirror.js +0 -15
- package/dist/cjs/tiptap/hooks/useTiptapEditor.js +0 -43
- package/dist/cjs/tiptap/hooks/useTiptapEditorEffect.js +0 -35
- package/dist/cjs/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
- package/dist/cjs/tiptap/index.js +0 -48
- package/dist/cjs/tiptap/tiptapNodeView.js +0 -237
- package/dist/esm/components/CustomNodeView.js +0 -81
- package/dist/esm/components/DefaultNodeView.js +0 -16
- package/dist/esm/components/DocNodeView.js +0 -45
- package/dist/esm/components/MarkView.js +0 -68
- package/dist/esm/components/NodeView.js +0 -35
- package/dist/esm/components/NodeViewComponentProps.js +0 -1
- package/dist/esm/components/ReactNodeView.js +0 -123
- package/dist/esm/components/marks/OldMarkView.js +0 -69
- package/dist/esm/tiptap/ReactProseMirrorNodeView.js +0 -22
- package/dist/esm/tiptap/TiptapEditor.js +0 -24
- package/dist/esm/tiptap/TiptapEditorContent.js +0 -91
- package/dist/esm/tiptap/TiptapEditorView.js +0 -69
- package/dist/esm/tiptap/TiptapNodeView.js +0 -22
- package/dist/esm/tiptap/contexts/TiptapEditorContext.js +0 -2
- package/dist/esm/tiptap/extensions/ReactProseMirror.js +0 -30
- package/dist/esm/tiptap/hooks/useIsInReactProseMirror.js +0 -5
- package/dist/esm/tiptap/hooks/useTiptapEditor.js +0 -33
- package/dist/esm/tiptap/hooks/useTiptapEditorEffect.js +0 -42
- package/dist/esm/tiptap/hooks/useTiptapEditorEventCallback.js +0 -35
- package/dist/esm/tiptap/index.js +0 -9
- package/dist/esm/tiptap/tiptapNodeView.js +0 -205
- package/dist/types/components/DefaultNodeView.d.ts +0 -3
- package/dist/types/components/DocNodeView.d.ts +0 -12
- package/dist/types/components/MarkView.d.ts +0 -9
- package/dist/types/components/NodeView.d.ts +0 -11
- package/dist/types/components/NodeViewComponentProps.d.ts +0 -12
- package/dist/types/components/ReactNodeView.d.ts +0 -13
- package/dist/types/components/marks/OldMarkView.d.ts +0 -10
- package/dist/types/components/nodes/CustomNodeView.d.ts +0 -12
- package/dist/types/tiptap/ReactProseMirrorNodeView.d.ts +0 -15
- package/dist/types/tiptap/TiptapEditor.d.ts +0 -6
- package/dist/types/tiptap/TiptapEditorContent.d.ts +0 -19
- package/dist/types/tiptap/TiptapEditorView.d.ts +0 -16
- package/dist/types/tiptap/TiptapNodeView.d.ts +0 -15
- package/dist/types/tiptap/contexts/TiptapEditorContext.d.ts +0 -6
- package/dist/types/tiptap/extensions/ReactProseMirror.d.ts +0 -9
- package/dist/types/tiptap/hooks/useIsInReactProseMirror.d.ts +0 -1
- package/dist/types/tiptap/hooks/useTiptapEditor.d.ts +0 -4
- package/dist/types/tiptap/hooks/useTiptapEditorEffect.d.ts +0 -21
- package/dist/types/tiptap/hooks/useTiptapEditorEventCallback.d.ts +0 -13
- package/dist/types/tiptap/index.d.ts +0 -9
- package/dist/types/tiptap/tiptapNodeView.d.ts +0 -50
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import React, { createElement, forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
|
|
2
|
+
import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
|
|
3
|
+
import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
|
|
4
4
|
import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
|
|
5
5
|
export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function DocNodeView(param, ref) {
|
|
6
6
|
let { as, node, getPos, decorations, innerDecorations, setMount, ...elementProps } = param;
|
|
@@ -11,14 +11,15 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
|
|
|
11
11
|
node,
|
|
12
12
|
getPos,
|
|
13
13
|
decorations,
|
|
14
|
-
innerDecorations
|
|
14
|
+
innerDecorations,
|
|
15
|
+
contentDOMRef: innerRef
|
|
15
16
|
}), [
|
|
16
17
|
node,
|
|
17
18
|
getPos,
|
|
18
19
|
decorations,
|
|
19
20
|
innerDecorations
|
|
20
21
|
]);
|
|
21
|
-
const { childContextValue } =
|
|
22
|
+
const { childContextValue } = useNodeViewDescription(()=>innerRef.current, ()=>innerRef.current, ()=>{
|
|
22
23
|
const dom = innerRef.current;
|
|
23
24
|
return {
|
|
24
25
|
dom,
|
|
@@ -28,7 +29,7 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
|
|
|
28
29
|
}
|
|
29
30
|
};
|
|
30
31
|
}, nodeProps);
|
|
31
|
-
const children = /*#__PURE__*/ React.createElement(
|
|
32
|
+
const children = /*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
|
|
32
33
|
value: childContextValue
|
|
33
34
|
}, /*#__PURE__*/ React.createElement(ChildNodeViews, {
|
|
34
35
|
getPos: getPos,
|
|
@@ -40,6 +41,6 @@ export const DocNodeView = /*#__PURE__*/ memo(/*#__PURE__*/ forwardRef(function
|
|
|
40
41
|
suppressContentEditableWarning: true,
|
|
41
42
|
ref: innerRef
|
|
42
43
|
};
|
|
43
|
-
const element = as ? /*#__PURE__*/
|
|
44
|
+
const element = as ? /*#__PURE__*/ createElement(as, props, children) : /*#__PURE__*/ createElement("div", props, children);
|
|
44
45
|
return nodeProps.decorations.reduce(wrapInDeco, element);
|
|
45
46
|
}));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import React, { memo, useContext, useMemo } from "react";
|
|
1
|
+
import React, { createContext, memo, useContext, useMemo } from "react";
|
|
2
2
|
import { NodeViewContext } from "../../contexts/NodeViewContext.js";
|
|
3
|
-
import { CustomNodeView } from "./CustomNodeView.js";
|
|
4
3
|
import { DefaultNodeView } from "./DefaultNodeView.js";
|
|
4
|
+
import { NodeViewConstructorView } from "./NodeViewConstructorView.js";
|
|
5
5
|
import { ReactNodeView } from "./ReactNodeView.js";
|
|
6
6
|
export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
|
|
7
7
|
const { components, constructors } = useContext(NodeViewContext);
|
|
@@ -14,7 +14,7 @@ export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
|
|
|
14
14
|
const Component = useMemo(()=>{
|
|
15
15
|
if (constructor) {
|
|
16
16
|
return function NodeView(props) {
|
|
17
|
-
return /*#__PURE__*/ React.createElement(
|
|
17
|
+
return /*#__PURE__*/ React.createElement(NodeViewConstructorView, {
|
|
18
18
|
constructor: constructor,
|
|
19
19
|
...props
|
|
20
20
|
});
|
|
@@ -31,5 +31,8 @@ export const NodeView = /*#__PURE__*/ memo(function NodeView(props) {
|
|
|
31
31
|
constructor,
|
|
32
32
|
component
|
|
33
33
|
]);
|
|
34
|
-
return /*#__PURE__*/ React.createElement(
|
|
34
|
+
return /*#__PURE__*/ React.createElement(GetPosContext.Provider, {
|
|
35
|
+
value: props.getPos
|
|
36
|
+
}, /*#__PURE__*/ React.createElement(Component, props));
|
|
35
37
|
});
|
|
38
|
+
export const GetPosContext = /*#__PURE__*/ createContext(null);
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { DOMSerializer } from "prosemirror-model";
|
|
2
2
|
import React, { cloneElement, memo, useMemo, useRef } from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
|
|
5
|
+
import { useForceUpdate } from "../../hooks/useForceUpdate.js";
|
|
6
|
+
import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
|
|
6
7
|
import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
|
|
7
|
-
export const
|
|
8
|
+
export const NodeViewConstructorView = /*#__PURE__*/ memo(function NodeViewConstructorView(param) {
|
|
8
9
|
let { constructor, node, getPos, innerDeco, outerDeco } = param;
|
|
9
10
|
const ref = useRef(null);
|
|
10
11
|
const innerRef = useRef(null);
|
|
12
|
+
const forceUpdate = useForceUpdate();
|
|
11
13
|
const nodeProps = useMemo(()=>({
|
|
12
14
|
node,
|
|
13
15
|
getPos,
|
|
14
16
|
decorations: outerDeco,
|
|
15
|
-
innerDecorations: innerDeco
|
|
17
|
+
innerDecorations: innerDeco,
|
|
18
|
+
contentDOMRef: {
|
|
19
|
+
current: null
|
|
20
|
+
}
|
|
16
21
|
}), [
|
|
17
22
|
node,
|
|
18
23
|
getPos,
|
|
@@ -33,7 +38,7 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
|
|
|
33
38
|
}
|
|
34
39
|
return nodeView;
|
|
35
40
|
};
|
|
36
|
-
const { childContextValue, contentDOM } =
|
|
41
|
+
const { childContextValue, contentDOM } = useNodeViewDescription(()=>ref.current, (source)=>source?.contentDOM ?? null, function() {
|
|
37
42
|
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
38
43
|
args[_key] = arguments[_key];
|
|
39
44
|
}
|
|
@@ -50,14 +55,22 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
|
|
|
50
55
|
nodeDOM.draggable = true;
|
|
51
56
|
}
|
|
52
57
|
}
|
|
58
|
+
if (contentDOM) {
|
|
59
|
+
// Force a re-render if we have a contentDOM,
|
|
60
|
+
// so that we properly create a portal into it
|
|
61
|
+
forceUpdate();
|
|
62
|
+
}
|
|
53
63
|
return {
|
|
54
|
-
...nodeView,
|
|
55
64
|
destroy () {
|
|
56
65
|
if (nodeView.destroy) {
|
|
57
66
|
nodeView.destroy();
|
|
58
67
|
}
|
|
59
68
|
wrapperDOM.removeChild(nodeDOM);
|
|
60
69
|
},
|
|
70
|
+
dom: nodeView.dom,
|
|
71
|
+
contentDOM: nodeView.contentDOM,
|
|
72
|
+
multiType: nodeView.multiType,
|
|
73
|
+
update: nodeView.update?.bind(nodeView),
|
|
61
74
|
selectNode: nodeView.selectNode?.bind(nodeView),
|
|
62
75
|
deselectNode: nodeView.deselectNode?.bind(nodeView),
|
|
63
76
|
stopEvent: nodeView.stopEvent?.bind(nodeView),
|
|
@@ -68,7 +81,7 @@ export const CustomNodeView = /*#__PURE__*/ memo(function CustomNodeView(param)
|
|
|
68
81
|
const props = {
|
|
69
82
|
ref: innerRef
|
|
70
83
|
};
|
|
71
|
-
const children = !node.isLeaf && contentDOM ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(
|
|
84
|
+
const children = !node.isLeaf && contentDOM ? /*#__PURE__*/ createPortal(/*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
|
|
72
85
|
value: childContextValue
|
|
73
86
|
}, /*#__PURE__*/ React.createElement(ChildNodeViews, {
|
|
74
87
|
getPos: getPos,
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import React, { cloneElement, memo, useCallback, useMemo, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ChildDescriptionsContext } from "../../contexts/ChildDescriptionsContext.js";
|
|
3
3
|
import { IgnoreMutationContext } from "../../contexts/IgnoreMutationContext.js";
|
|
4
4
|
import { SelectNodeContext } from "../../contexts/SelectNodeContext.js";
|
|
5
5
|
import { StopEventContext } from "../../contexts/StopEventContext.js";
|
|
6
|
-
import {
|
|
6
|
+
import { useForceUpdate } from "../../hooks/useForceUpdate.js";
|
|
7
|
+
import { useNodeViewDescription } from "../../hooks/useNodeViewDescription.js";
|
|
7
8
|
import { ChildNodeViews, wrapInDeco } from "../ChildNodeViews.js";
|
|
8
9
|
export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
9
10
|
let { component: Component, outerDeco, getPos, node, innerDeco } = param;
|
|
10
11
|
const [hasCustomSelectNode, setHasCustomSelectNode] = useState(false);
|
|
11
12
|
const [selected, setSelected] = useState(false);
|
|
12
|
-
const
|
|
13
|
-
const
|
|
13
|
+
const forceUpdate = useForceUpdate();
|
|
14
|
+
const domRef = useRef(null);
|
|
15
|
+
const nodeDOMRef = useRef(null);
|
|
16
|
+
const contentDOMRef = useRef(null);
|
|
14
17
|
const selectNodeRef = useRef(null);
|
|
15
18
|
const deselectNodeRef = useRef(null);
|
|
16
19
|
const stopEventRef = useRef(null);
|
|
@@ -40,7 +43,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
40
43
|
};
|
|
41
44
|
};
|
|
42
45
|
}, []);
|
|
43
|
-
const
|
|
46
|
+
const nodeViewDescProps = useMemo(()=>({
|
|
44
47
|
node: node,
|
|
45
48
|
getPos: getPos,
|
|
46
49
|
decorations: outerDeco,
|
|
@@ -51,10 +54,10 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
51
54
|
node,
|
|
52
55
|
outerDeco
|
|
53
56
|
]);
|
|
54
|
-
const { childContextValue,
|
|
57
|
+
const { childContextValue, refUpdated } = useNodeViewDescription(()=>domRef.current, ()=>contentDOMRef.current, ()=>{
|
|
55
58
|
setSelected(false);
|
|
56
59
|
return {
|
|
57
|
-
dom:
|
|
60
|
+
dom: nodeDOMRef.current ?? domRef.current,
|
|
58
61
|
update () {
|
|
59
62
|
return true;
|
|
60
63
|
},
|
|
@@ -62,46 +65,85 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
62
65
|
selectNode () {
|
|
63
66
|
const selectNode = selectNodeRef.current;
|
|
64
67
|
if (selectNode) {
|
|
65
|
-
selectNode
|
|
68
|
+
selectNode();
|
|
66
69
|
}
|
|
67
70
|
setSelected(true);
|
|
68
71
|
},
|
|
69
72
|
deselectNode () {
|
|
70
73
|
const deselectNode = deselectNodeRef.current;
|
|
71
74
|
if (deselectNode) {
|
|
72
|
-
deselectNode
|
|
75
|
+
deselectNode();
|
|
73
76
|
}
|
|
74
77
|
setSelected(false);
|
|
75
78
|
},
|
|
76
79
|
stopEvent (event) {
|
|
77
80
|
const stopEvent = stopEventRef.current;
|
|
78
81
|
if (stopEvent) {
|
|
79
|
-
return stopEvent
|
|
82
|
+
return stopEvent(event);
|
|
80
83
|
}
|
|
81
84
|
return false;
|
|
82
85
|
},
|
|
83
86
|
ignoreMutation (mutation) {
|
|
84
87
|
const ignoreMutation = ignoreMutationRef.current;
|
|
85
88
|
if (ignoreMutation) {
|
|
86
|
-
return ignoreMutation
|
|
89
|
+
return ignoreMutation(mutation);
|
|
87
90
|
}
|
|
88
91
|
return false;
|
|
89
92
|
}
|
|
90
93
|
};
|
|
91
|
-
},
|
|
94
|
+
}, nodeViewDescProps);
|
|
95
|
+
const setDOM = useCallback((el)=>{
|
|
96
|
+
domRef.current = el;
|
|
97
|
+
refUpdated();
|
|
98
|
+
}, [
|
|
99
|
+
refUpdated
|
|
100
|
+
]);
|
|
101
|
+
const setNodeDOM = useCallback((el)=>{
|
|
102
|
+
if (!!nodeDOMRef.current !== !!el) {
|
|
103
|
+
// Force a re-render if the existence of nodeDOM
|
|
104
|
+
// is changing, since we use its existince to set
|
|
105
|
+
// some props
|
|
106
|
+
forceUpdate();
|
|
107
|
+
}
|
|
108
|
+
nodeDOMRef.current = el;
|
|
109
|
+
refUpdated();
|
|
110
|
+
}, [
|
|
111
|
+
forceUpdate,
|
|
112
|
+
refUpdated
|
|
113
|
+
]);
|
|
114
|
+
const setContentDOM = useCallback((el)=>{
|
|
115
|
+
if (!!contentDOMRef.current !== !!el) {
|
|
116
|
+
// Force a re-render if the existence of contentDOM
|
|
117
|
+
// is changing, since we use its existince to set
|
|
118
|
+
// some props
|
|
119
|
+
forceUpdate();
|
|
120
|
+
}
|
|
121
|
+
contentDOMRef.current = el;
|
|
122
|
+
refUpdated();
|
|
123
|
+
}, [
|
|
124
|
+
forceUpdate,
|
|
125
|
+
refUpdated
|
|
126
|
+
]);
|
|
127
|
+
const nodeProps = useMemo(()=>({
|
|
128
|
+
...nodeViewDescProps,
|
|
129
|
+
contentDOMRef: setContentDOM
|
|
130
|
+
}), [
|
|
131
|
+
nodeViewDescProps,
|
|
132
|
+
setContentDOM
|
|
133
|
+
]);
|
|
92
134
|
const props = {
|
|
93
135
|
nodeProps,
|
|
94
|
-
...!
|
|
136
|
+
...!contentDOMRef.current && !nodeProps.node.isText && nodeDOMRef.current?.nodeName !== "BR" ? {
|
|
95
137
|
contentEditable: false,
|
|
96
138
|
suppressContentEditableWarning: true
|
|
97
139
|
} : null,
|
|
98
140
|
...!hasCustomSelectNode && selected ? {
|
|
99
141
|
className: "ProseMirror-selectednode"
|
|
100
142
|
} : null,
|
|
101
|
-
...!hasCustomSelectNode && selected || node.type.spec.draggable ? {
|
|
143
|
+
...!hasCustomSelectNode && selected || !contentDOMRef.current && !nodeProps.node.isText && domRef.current?.nodeName !== "BR" && node.type.spec.draggable ? {
|
|
102
144
|
draggable: true
|
|
103
145
|
} : null,
|
|
104
|
-
ref:
|
|
146
|
+
ref: setNodeDOM
|
|
105
147
|
};
|
|
106
148
|
const children = !node.isLeaf ? /*#__PURE__*/ React.createElement(ChildNodeViews, {
|
|
107
149
|
getPos: getPos,
|
|
@@ -109,7 +151,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
109
151
|
innerDecorations: innerDeco
|
|
110
152
|
}) : null;
|
|
111
153
|
const element = /*#__PURE__*/ cloneElement(outerDeco.reduce(wrapInDeco, /*#__PURE__*/ React.createElement(Component, props, children)), {
|
|
112
|
-
ref
|
|
154
|
+
ref: setDOM
|
|
113
155
|
});
|
|
114
156
|
return /*#__PURE__*/ React.createElement(SelectNodeContext.Provider, {
|
|
115
157
|
value: setSelectNode
|
|
@@ -117,7 +159,7 @@ export const ReactNodeView = /*#__PURE__*/ memo(function ReactNodeView(param) {
|
|
|
117
159
|
value: setStopEvent
|
|
118
160
|
}, /*#__PURE__*/ React.createElement(IgnoreMutationContext.Provider, {
|
|
119
161
|
value: setIgnoreMutation
|
|
120
|
-
}, /*#__PURE__*/ React.createElement(
|
|
162
|
+
}, /*#__PURE__*/ React.createElement(ChildDescriptionsContext.Provider, {
|
|
121
163
|
value: childContextValue
|
|
122
164
|
}, element))));
|
|
123
165
|
});
|
|
@@ -101,11 +101,7 @@ let didWarnValueDefaultValue = false;
|
|
|
101
101
|
// running effects. Running effects will reattach selection
|
|
102
102
|
// change listeners if the EditorView has been destroyed.
|
|
103
103
|
if (view instanceof ReactEditorView && !view.isDestroyed) {
|
|
104
|
-
// Plugins might dispatch transactions from their
|
|
105
|
-
// view update lifecycle hooks
|
|
106
|
-
flushSyncRef.current = false;
|
|
107
104
|
view.commitPendingEffects();
|
|
108
|
-
flushSyncRef.current = true;
|
|
109
105
|
}
|
|
110
106
|
});
|
|
111
107
|
view.update(directEditorProps);
|
|
@@ -15,10 +15,6 @@ import { useLayoutGroupEffect } from "./useLayoutGroupEffect.js";
|
|
|
15
15
|
* synchronously after all DOM mutations, but they do so
|
|
16
16
|
* _after_ the EditorView has been updated, even when the
|
|
17
17
|
* EditorView lives in an ancestor component.
|
|
18
|
-
*
|
|
19
|
-
* This hook can only be used in a component that is mounted
|
|
20
|
-
* as a child of the TiptapEditorView component, including
|
|
21
|
-
* React node view components.
|
|
22
18
|
*/ export function useEditorEffect(effect, dependencies) {
|
|
23
19
|
const { view, flushSyncRef } = useContext(EditorContext);
|
|
24
20
|
// The rules of hooks want `effect` to be included in the
|
|
@@ -15,9 +15,11 @@ function assertIsReactEditorView(view) {
|
|
|
15
15
|
* The callback will be called with the EditorView instance
|
|
16
16
|
* as its first argument.
|
|
17
17
|
*
|
|
18
|
-
* This hook
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* This hook is dependent on both the
|
|
19
|
+
* `EditorViewContext.Provider` and the
|
|
20
|
+
* `DeferredLayoutEffectProvider`. It can only be used in a
|
|
21
|
+
* component that is mounted as a child of both of these
|
|
22
|
+
* providers.
|
|
21
23
|
*/ export function useEditorEventCallback(callback) {
|
|
22
24
|
const ref = useRef(callback);
|
|
23
25
|
const { view } = useContext(EditorContext);
|
|
@@ -31,7 +33,7 @@ function assertIsReactEditorView(view) {
|
|
|
31
33
|
args[_key] = arguments[_key];
|
|
32
34
|
}
|
|
33
35
|
assertIsReactEditorView(view);
|
|
34
|
-
return ref.current
|
|
36
|
+
return ref.current(view, ...args);
|
|
35
37
|
}, [
|
|
36
38
|
view
|
|
37
39
|
]);
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import { useContext, useMemo, useRef
|
|
1
|
+
import { useCallback, useContext, useMemo, useRef } from "react";
|
|
2
2
|
import { ReactEditorView } from "../ReactEditorView.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js";
|
|
4
4
|
import { EditorContext } from "../contexts/EditorContext.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ReactMarkViewDesc, sortViewDescs } from "../viewdesc.js";
|
|
6
6
|
import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
|
|
7
7
|
import { useEffectEvent } from "./useEffectEvent.js";
|
|
8
|
-
function
|
|
9
|
-
return source?.contentDOM ?? children[0]?.dom?.parentElement ?? dom;
|
|
10
|
-
}
|
|
11
|
-
export function useMarkViewDescription(ref, constructor, props) {
|
|
8
|
+
export function useMarkViewDescription(getDOM, getContentDOM, constructor, props) {
|
|
12
9
|
const { view } = useContext(EditorContext);
|
|
13
|
-
const { parentRef, siblingsRef } = useContext(
|
|
14
|
-
const
|
|
15
|
-
const [contentDOM, setContentDOM] = useState(null);
|
|
10
|
+
const { parentRef, siblingsRef } = useContext(ChildDescriptionsContext);
|
|
11
|
+
const contentDOMRef = useRef(null);
|
|
16
12
|
const viewDescRef = useRef();
|
|
17
13
|
const childrenRef = useRef([]);
|
|
18
14
|
const create = useEffectEvent(()=>{
|
|
19
15
|
if (!(view instanceof ReactEditorView)) {
|
|
20
16
|
return;
|
|
21
17
|
}
|
|
22
|
-
const dom =
|
|
18
|
+
const dom = getDOM();
|
|
23
19
|
if (!dom) {
|
|
24
20
|
return;
|
|
25
21
|
}
|
|
@@ -30,10 +26,9 @@ export function useMarkViewDescription(ref, constructor, props) {
|
|
|
30
26
|
}
|
|
31
27
|
const parent = parentRef.current;
|
|
32
28
|
const children = childrenRef.current;
|
|
33
|
-
const contentDOM =
|
|
34
|
-
const viewDesc = new
|
|
35
|
-
|
|
36
|
-
setContentDOM(contentDOM);
|
|
29
|
+
const contentDOM = getContentDOM(markView);
|
|
30
|
+
const viewDesc = new ReactMarkViewDesc(parent, children, getPos, mark, dom, contentDOM ?? markView.dom, markView);
|
|
31
|
+
contentDOMRef.current = contentDOM;
|
|
37
32
|
return viewDesc;
|
|
38
33
|
});
|
|
39
34
|
const update = useEffectEvent(()=>{
|
|
@@ -44,12 +39,12 @@ export function useMarkViewDescription(ref, constructor, props) {
|
|
|
44
39
|
if (!viewDesc) {
|
|
45
40
|
return false;
|
|
46
41
|
}
|
|
47
|
-
const dom =
|
|
42
|
+
const dom = getDOM();
|
|
48
43
|
if (!dom || dom !== viewDesc.dom) {
|
|
49
44
|
return false;
|
|
50
45
|
}
|
|
51
|
-
const contentDOM =
|
|
52
|
-
if (contentDOM !== viewDesc.contentDOM) {
|
|
46
|
+
const contentDOM = getContentDOM(viewDesc);
|
|
47
|
+
if (contentDOM !== (viewDesc.contentDOM ?? dom)) {
|
|
53
48
|
return false;
|
|
54
49
|
}
|
|
55
50
|
const { mark } = props;
|
|
@@ -66,8 +61,7 @@ export function useMarkViewDescription(ref, constructor, props) {
|
|
|
66
61
|
const index = siblings.indexOf(viewDesc);
|
|
67
62
|
siblings.splice(index, 1);
|
|
68
63
|
}
|
|
69
|
-
|
|
70
|
-
setContentDOM(null);
|
|
64
|
+
contentDOMRef.current = null;
|
|
71
65
|
});
|
|
72
66
|
useClientLayoutEffect(()=>{
|
|
73
67
|
viewDescRef.current = create();
|
|
@@ -78,6 +72,16 @@ export function useMarkViewDescription(ref, constructor, props) {
|
|
|
78
72
|
create,
|
|
79
73
|
destroy
|
|
80
74
|
]);
|
|
75
|
+
const refUpdated = useCallback(()=>{
|
|
76
|
+
if (!update()) {
|
|
77
|
+
destroy();
|
|
78
|
+
viewDescRef.current = create();
|
|
79
|
+
}
|
|
80
|
+
}, [
|
|
81
|
+
create,
|
|
82
|
+
destroy,
|
|
83
|
+
update
|
|
84
|
+
]);
|
|
81
85
|
useClientLayoutEffect(()=>{
|
|
82
86
|
if (!update()) {
|
|
83
87
|
destroy();
|
|
@@ -108,8 +112,7 @@ export function useMarkViewDescription(ref, constructor, props) {
|
|
|
108
112
|
]);
|
|
109
113
|
return {
|
|
110
114
|
childContextValue,
|
|
111
|
-
dom,
|
|
112
|
-
|
|
113
|
-
ref
|
|
115
|
+
contentDOM: contentDOMRef.current ?? viewDescRef.current?.dom,
|
|
116
|
+
refUpdated
|
|
114
117
|
};
|
|
115
118
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { GetPosContext } from "../components/nodes/NodeView.js";
|
|
3
|
+
import { useEditorState } from "./useEditorState.js";
|
|
4
|
+
/**
|
|
5
|
+
* Get this node's current position in the document.
|
|
6
|
+
*
|
|
7
|
+
* Using this hook will subscribe this node to the
|
|
8
|
+
* EditorState, which means that it will be re-rendered
|
|
9
|
+
* on every EditorState update. This may have performance
|
|
10
|
+
* implications for large documents.
|
|
11
|
+
*/ export function useNodePos() {
|
|
12
|
+
useEditorState();
|
|
13
|
+
const getPos = useContext(GetPosContext);
|
|
14
|
+
return getPos();
|
|
15
|
+
}
|
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
import { useContext, useMemo, useRef
|
|
1
|
+
import { useCallback, useContext, useMemo, useRef } from "react";
|
|
2
2
|
import { ReactEditorView } from "../ReactEditorView.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ChildDescriptionsContext } from "../contexts/ChildDescriptionsContext.js";
|
|
4
4
|
import { EditorContext } from "../contexts/EditorContext.js";
|
|
5
5
|
import { CompositionViewDesc, ReactNodeViewDesc, sortViewDescs } from "../viewdesc.js";
|
|
6
6
|
import { useClientLayoutEffect } from "./useClientLayoutEffect.js";
|
|
7
7
|
import { useEffectEvent } from "./useEffectEvent.js";
|
|
8
|
-
function
|
|
9
|
-
return source?.contentDOM ?? children[0]?.dom?.parentElement ?? null;
|
|
10
|
-
}
|
|
11
|
-
export function useNodeViewDescriptor(ref, constructor, props) {
|
|
8
|
+
export function useNodeViewDescription(getDOM, getContentDOM, constructor, props) {
|
|
12
9
|
const { view } = useContext(EditorContext);
|
|
13
|
-
const { parentRef, siblingsRef } = useContext(
|
|
14
|
-
const
|
|
15
|
-
const [nodeDOM, setNodeDOM] = useState(null);
|
|
16
|
-
const [contentDOM, setContentDOM] = useState(null);
|
|
10
|
+
const { parentRef, siblingsRef } = useContext(ChildDescriptionsContext);
|
|
11
|
+
const contentDOMRef = useRef(null);
|
|
17
12
|
const viewDescRef = useRef();
|
|
18
13
|
const childrenRef = useRef([]);
|
|
19
14
|
const create = useEffectEvent(()=>{
|
|
20
15
|
if (!(view instanceof ReactEditorView)) {
|
|
21
16
|
return;
|
|
22
17
|
}
|
|
23
|
-
const dom =
|
|
18
|
+
const dom = getDOM();
|
|
24
19
|
if (!dom) {
|
|
25
20
|
return;
|
|
26
21
|
}
|
|
@@ -31,12 +26,15 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
31
26
|
}
|
|
32
27
|
const parent = parentRef.current;
|
|
33
28
|
const children = childrenRef.current;
|
|
34
|
-
const contentDOM =
|
|
29
|
+
const contentDOM = getContentDOM(nodeView);
|
|
35
30
|
const nodeDOM = nodeView.dom;
|
|
36
31
|
const viewDesc = new ReactNodeViewDesc(parent, children, getPos, node, decorations, innerDecorations, dom, contentDOM, nodeDOM, nodeView);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
const siblings = siblingsRef.current;
|
|
33
|
+
if (!siblings.includes(viewDesc)) {
|
|
34
|
+
siblings.push(viewDesc);
|
|
35
|
+
}
|
|
36
|
+
siblings.sort(sortViewDescs);
|
|
37
|
+
contentDOMRef.current = getContentDOM(nodeView);
|
|
40
38
|
return viewDesc;
|
|
41
39
|
});
|
|
42
40
|
const update = useEffectEvent(()=>{
|
|
@@ -47,11 +45,11 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
47
45
|
if (!viewDesc) {
|
|
48
46
|
return false;
|
|
49
47
|
}
|
|
50
|
-
const dom =
|
|
48
|
+
const dom = getDOM();
|
|
51
49
|
if (!dom || dom !== viewDesc.dom) {
|
|
52
50
|
return false;
|
|
53
51
|
}
|
|
54
|
-
const contentDOM =
|
|
52
|
+
const contentDOM = getContentDOM(viewDesc);
|
|
55
53
|
if (contentDOM !== viewDesc.contentDOM) {
|
|
56
54
|
return false;
|
|
57
55
|
}
|
|
@@ -72,9 +70,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
72
70
|
const index = siblings.indexOf(viewDesc);
|
|
73
71
|
siblings.splice(index, 1);
|
|
74
72
|
}
|
|
75
|
-
|
|
76
|
-
setContentDOM(null);
|
|
77
|
-
setNodeDOM(null);
|
|
73
|
+
contentDOMRef.current = null;
|
|
78
74
|
});
|
|
79
75
|
useClientLayoutEffect(()=>{
|
|
80
76
|
viewDescRef.current = create();
|
|
@@ -85,6 +81,17 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
85
81
|
create,
|
|
86
82
|
destroy
|
|
87
83
|
]);
|
|
84
|
+
const refUpdated = useCallback(()=>{
|
|
85
|
+
if (!viewDescRef.current) return;
|
|
86
|
+
if (!update()) {
|
|
87
|
+
destroy();
|
|
88
|
+
viewDescRef.current = create();
|
|
89
|
+
}
|
|
90
|
+
}, [
|
|
91
|
+
create,
|
|
92
|
+
destroy,
|
|
93
|
+
update
|
|
94
|
+
]);
|
|
88
95
|
useClientLayoutEffect(()=>{
|
|
89
96
|
if (!update()) {
|
|
90
97
|
destroy();
|
|
@@ -136,9 +143,7 @@ export function useNodeViewDescriptor(ref, constructor, props) {
|
|
|
136
143
|
]);
|
|
137
144
|
return {
|
|
138
145
|
childContextValue,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
nodeDOM,
|
|
142
|
-
ref
|
|
146
|
+
contentDOM: contentDOMRef.current,
|
|
147
|
+
refUpdated
|
|
143
148
|
};
|
|
144
149
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { useEditorEffect } from "./hooks/useEditorEffect.js";
|
|
|
6
6
|
export { useEditorEventCallback } from "./hooks/useEditorEventCallback.js";
|
|
7
7
|
export { useEditorEventListener } from "./hooks/useEditorEventListener.js";
|
|
8
8
|
export { useEditorState } from "./hooks/useEditorState.js";
|
|
9
|
+
export { useNodePos } from "./hooks/useNodePos.js";
|
|
9
10
|
export { useStopEvent } from "./hooks/useStopEvent.js";
|
|
10
11
|
export { useSelectNode } from "./hooks/useSelectNode.js";
|
|
11
12
|
export { useIgnoreMutation } from "./hooks/useIgnoreMutation.js";
|
|
@@ -13,3 +14,4 @@ export { useIsEditorStatic } from "./hooks/useIsEditorStatic.js";
|
|
|
13
14
|
export { useIsNodeSelected } from "./hooks/useIsNodeSelected.js";
|
|
14
15
|
export { reactKeys } from "./plugins/reactKeys.js";
|
|
15
16
|
export { widget } from "./decorations/ReactWidgetType.js";
|
|
17
|
+
export { useMergedDOMRefs } from "./refs.js";
|
package/dist/esm/refs.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
export function useMergedDOMRefs() {
|
|
3
|
+
for(var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++){
|
|
4
|
+
refs[_key] = arguments[_key];
|
|
5
|
+
}
|
|
6
|
+
return useCallback((value)=>{
|
|
7
|
+
refs.forEach((ref)=>{
|
|
8
|
+
if (typeof ref === "function") {
|
|
9
|
+
ref(value);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (ref) {
|
|
13
|
+
ref.current = value;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
17
|
+
}, refs);
|
|
18
|
+
}
|
package/dist/esm/viewdesc.js
CHANGED
|
@@ -711,25 +711,32 @@ let CustomNodeViewDesc = class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
713
|
selectNode() {
|
|
714
|
-
this.spec.selectNode ? this.spec.selectNode
|
|
714
|
+
this.spec.selectNode ? this.spec.selectNode() : super.selectNode();
|
|
715
715
|
}
|
|
716
716
|
deselectNode() {
|
|
717
|
-
this.spec.deselectNode ? this.spec.deselectNode
|
|
717
|
+
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
|
|
718
718
|
}
|
|
719
719
|
setSelection(anchor, head, view, force) {
|
|
720
|
-
this.spec.setSelection ? this.spec.setSelection
|
|
720
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root) : super.setSelection(anchor, head, view, force);
|
|
721
721
|
}
|
|
722
722
|
destroy() {
|
|
723
723
|
if (this.spec.destroy) this.spec.destroy();
|
|
724
724
|
super.destroy();
|
|
725
725
|
}
|
|
726
726
|
stopEvent(event) {
|
|
727
|
-
return this.spec.stopEvent ? this.spec.stopEvent
|
|
727
|
+
return this.spec.stopEvent ? this.spec.stopEvent(event) : false;
|
|
728
728
|
}
|
|
729
729
|
ignoreMutation(mutation) {
|
|
730
|
-
return this.spec.ignoreMutation ? this.spec.ignoreMutation
|
|
730
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
|
|
731
731
|
}
|
|
732
732
|
};
|
|
733
|
+
export class ReactMarkViewDesc extends MarkViewDesc {
|
|
734
|
+
destroy() {
|
|
735
|
+
// React has already destroyed the children (if needed).
|
|
736
|
+
this.children = [];
|
|
737
|
+
super.destroy();
|
|
738
|
+
}
|
|
739
|
+
}
|
|
733
740
|
export class ReactNodeViewDesc extends CustomNodeViewDesc {
|
|
734
741
|
updateChildren(_view, _pos) {
|
|
735
742
|
// React has already updated the children.
|
|
@@ -744,7 +751,7 @@ export class ReactNodeViewDesc extends CustomNodeViewDesc {
|
|
|
744
751
|
super.destroy();
|
|
745
752
|
}
|
|
746
753
|
}
|
|
747
|
-
function sameOuterDeco(a, b) {
|
|
754
|
+
export function sameOuterDeco(a, b) {
|
|
748
755
|
if (a.length != b.length) return false;
|
|
749
756
|
// @ts-expect-error ...
|
|
750
757
|
for(let i = 0; i < a.length; i++)if (!a[i].type.eq(b[i].type)) return false;
|