@tiptap/react 2.5.0-beta.2 → 2.5.0-beta.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/dist/index.cjs +529 -536
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +527 -527
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +529 -536
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/CommandManager.d.ts +20 -0
- package/dist/packages/core/src/Editor.d.ts +161 -0
- package/dist/packages/core/src/EventEmitter.d.ts +11 -0
- package/dist/packages/core/src/Extension.d.ts +343 -0
- package/dist/packages/core/src/ExtensionManager.d.ts +55 -0
- package/dist/packages/core/src/InputRule.d.ts +42 -0
- package/dist/packages/core/src/Mark.d.ts +451 -0
- package/dist/packages/core/src/Node.d.ts +611 -0
- package/dist/packages/core/src/NodePos.d.ts +44 -0
- package/dist/packages/core/src/NodeView.d.ts +31 -0
- package/dist/packages/core/src/PasteRule.d.ts +50 -0
- package/dist/packages/core/src/Tracker.d.ts +11 -0
- package/dist/packages/core/src/commands/blur.d.ts +13 -0
- package/dist/packages/core/src/commands/clearContent.d.ts +14 -0
- package/dist/packages/core/src/commands/clearNodes.d.ts +13 -0
- package/dist/packages/core/src/commands/command.d.ts +18 -0
- package/dist/packages/core/src/commands/createParagraphNear.d.ts +13 -0
- package/dist/packages/core/src/commands/cut.d.ts +20 -0
- package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +13 -0
- package/dist/packages/core/src/commands/deleteNode.d.ts +15 -0
- package/dist/packages/core/src/commands/deleteRange.d.ts +14 -0
- package/dist/packages/core/src/commands/deleteSelection.d.ts +13 -0
- package/dist/packages/core/src/commands/enter.d.ts +13 -0
- package/dist/packages/core/src/commands/exitCode.d.ts +13 -0
- package/dist/packages/core/src/commands/extendMarkRange.d.ts +25 -0
- package/dist/packages/core/src/commands/first.d.ts +14 -0
- package/dist/packages/core/src/commands/focus.d.ts +27 -0
- package/dist/packages/core/src/commands/forEach.d.ts +14 -0
- package/dist/packages/core/src/commands/index.d.ts +55 -0
- package/dist/packages/core/src/commands/insertContent.d.ts +34 -0
- package/dist/packages/core/src/commands/insertContentAt.d.ts +47 -0
- package/dist/packages/core/src/commands/join.d.ts +41 -0
- package/dist/packages/core/src/commands/joinItemBackward.d.ts +13 -0
- package/dist/packages/core/src/commands/joinItemForward.d.ts +13 -0
- package/dist/packages/core/src/commands/joinTextblockBackward.d.ts +12 -0
- package/dist/packages/core/src/commands/joinTextblockForward.d.ts +12 -0
- package/dist/packages/core/src/commands/keyboardShortcut.d.ts +14 -0
- package/dist/packages/core/src/commands/lift.d.ts +17 -0
- package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +13 -0
- package/dist/packages/core/src/commands/liftListItem.d.ts +15 -0
- package/dist/packages/core/src/commands/newlineInCode.d.ts +13 -0
- package/dist/packages/core/src/commands/resetAttributes.d.ts +16 -0
- package/dist/packages/core/src/commands/scrollIntoView.d.ts +13 -0
- package/dist/packages/core/src/commands/selectAll.d.ts +13 -0
- package/dist/packages/core/src/commands/selectNodeBackward.d.ts +13 -0
- package/dist/packages/core/src/commands/selectNodeForward.d.ts +13 -0
- package/dist/packages/core/src/commands/selectParentNode.d.ts +13 -0
- package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +13 -0
- package/dist/packages/core/src/commands/selectTextblockStart.d.ts +13 -0
- package/dist/packages/core/src/commands/setContent.d.ts +40 -0
- package/dist/packages/core/src/commands/setMark.d.ts +15 -0
- package/dist/packages/core/src/commands/setMeta.d.ts +15 -0
- package/dist/packages/core/src/commands/setNode.d.ts +16 -0
- package/dist/packages/core/src/commands/setNodeSelection.d.ts +14 -0
- package/dist/packages/core/src/commands/setTextSelection.d.ts +14 -0
- package/dist/packages/core/src/commands/sinkListItem.d.ts +15 -0
- package/dist/packages/core/src/commands/splitBlock.d.ts +17 -0
- package/dist/packages/core/src/commands/splitListItem.d.ts +15 -0
- package/dist/packages/core/src/commands/toggleList.d.ts +18 -0
- package/dist/packages/core/src/commands/toggleMark.d.ts +30 -0
- package/dist/packages/core/src/commands/toggleNode.d.ts +17 -0
- package/dist/packages/core/src/commands/toggleWrap.d.ts +16 -0
- package/dist/packages/core/src/commands/undoInputRule.d.ts +13 -0
- package/dist/packages/core/src/commands/unsetAllMarks.d.ts +13 -0
- package/dist/packages/core/src/commands/unsetMark.d.ts +25 -0
- package/dist/packages/core/src/commands/updateAttributes.d.ts +24 -0
- package/dist/packages/core/src/commands/wrapIn.d.ts +16 -0
- package/dist/packages/core/src/commands/wrapInList.d.ts +16 -0
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +5 -0
- package/dist/packages/core/src/extensions/commands.d.ts +3 -0
- package/dist/packages/core/src/extensions/editable.d.ts +2 -0
- package/dist/packages/core/src/extensions/focusEvents.d.ts +2 -0
- package/dist/packages/core/src/extensions/index.d.ts +6 -0
- package/dist/packages/core/src/extensions/keymap.d.ts +2 -0
- package/dist/packages/core/src/extensions/tabindex.d.ts +2 -0
- package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +10 -0
- package/dist/packages/core/src/helpers/createChainableState.d.ts +10 -0
- package/dist/packages/core/src/helpers/createDocument.d.ts +12 -0
- package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +15 -0
- package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +7 -0
- package/dist/packages/core/src/helpers/findChildren.d.ts +9 -0
- package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +10 -0
- package/dist/packages/core/src/helpers/findParentNode.d.ts +16 -0
- package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +17 -0
- package/dist/packages/core/src/helpers/generateHTML.d.ts +8 -0
- package/dist/packages/core/src/helpers/generateJSON.d.ts +8 -0
- package/dist/packages/core/src/helpers/generateText.d.ts +12 -0
- package/dist/packages/core/src/helpers/getAttributes.d.ts +9 -0
- package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +6 -0
- package/dist/packages/core/src/helpers/getChangedRanges.d.ts +11 -0
- package/dist/packages/core/src/helpers/getDebugJSON.d.ts +8 -0
- package/dist/packages/core/src/helpers/getExtensionField.d.ts +9 -0
- package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +2 -0
- package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +3 -0
- package/dist/packages/core/src/helpers/getMarkRange.d.ts +3 -0
- package/dist/packages/core/src/helpers/getMarkType.d.ts +2 -0
- package/dist/packages/core/src/helpers/getMarksBetween.d.ts +3 -0
- package/dist/packages/core/src/helpers/getNodeAtPosition.d.ts +11 -0
- package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +3 -0
- package/dist/packages/core/src/helpers/getNodeType.d.ts +2 -0
- package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +3 -0
- package/dist/packages/core/src/helpers/getSchema.d.ts +4 -0
- package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +10 -0
- package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +8 -0
- package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +8 -0
- package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +9 -0
- package/dist/packages/core/src/helpers/getText.d.ts +15 -0
- package/dist/packages/core/src/helpers/getTextBetween.d.ts +14 -0
- package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +8 -0
- package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +8 -0
- package/dist/packages/core/src/helpers/index.d.ts +50 -0
- package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +9 -0
- package/dist/packages/core/src/helpers/isActive.d.ts +2 -0
- package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +2 -0
- package/dist/packages/core/src/helpers/isAtStartOfNode.d.ts +2 -0
- package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +2 -0
- package/dist/packages/core/src/helpers/isList.d.ts +2 -0
- package/dist/packages/core/src/helpers/isMarkActive.d.ts +3 -0
- package/dist/packages/core/src/helpers/isNodeActive.d.ts +3 -0
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +2 -0
- package/dist/packages/core/src/helpers/isNodeSelection.d.ts +2 -0
- package/dist/packages/core/src/helpers/isTextSelection.d.ts +2 -0
- package/dist/packages/core/src/helpers/posToDOMRect.d.ts +2 -0
- package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +4 -0
- package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +2 -0
- package/dist/packages/core/src/helpers/splitExtensions.d.ts +9 -0
- package/dist/packages/core/src/index.d.ts +24 -0
- package/dist/packages/core/src/inputRules/index.d.ts +5 -0
- package/dist/packages/core/src/inputRules/markInputRule.d.ts +13 -0
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +23 -0
- package/dist/packages/core/src/inputRules/textInputRule.d.ts +10 -0
- package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +15 -0
- package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +28 -0
- package/dist/packages/core/src/pasteRules/index.d.ts +3 -0
- package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +13 -0
- package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +13 -0
- package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +10 -0
- package/dist/packages/core/src/style.d.ts +1 -0
- package/dist/packages/core/src/types.d.ts +250 -0
- package/dist/packages/core/src/utilities/callOrReturn.d.ts +9 -0
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +1 -0
- package/dist/packages/core/src/utilities/deleteProps.d.ts +6 -0
- package/dist/packages/core/src/utilities/elementFromString.d.ts +1 -0
- package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +1 -0
- package/dist/packages/core/src/utilities/findDuplicates.d.ts +1 -0
- package/dist/packages/core/src/utilities/fromString.d.ts +1 -0
- package/dist/packages/core/src/utilities/index.d.ts +20 -0
- package/dist/packages/core/src/utilities/isAndroid.d.ts +1 -0
- package/dist/packages/core/src/utilities/isEmptyObject.d.ts +1 -0
- package/dist/packages/core/src/utilities/isFunction.d.ts +1 -0
- package/dist/packages/core/src/utilities/isMacOS.d.ts +1 -0
- package/dist/packages/core/src/utilities/isNumber.d.ts +1 -0
- package/dist/packages/core/src/utilities/isPlainObject.d.ts +1 -0
- package/dist/packages/core/src/utilities/isRegExp.d.ts +1 -0
- package/dist/packages/core/src/utilities/isString.d.ts +1 -0
- package/dist/packages/core/src/utilities/isiOS.d.ts +1 -0
- package/dist/packages/core/src/utilities/mergeAttributes.d.ts +1 -0
- package/dist/packages/core/src/utilities/mergeDeep.d.ts +1 -0
- package/dist/packages/core/src/utilities/minMax.d.ts +1 -0
- package/dist/packages/core/src/utilities/objectIncludes.d.ts +8 -0
- package/dist/packages/core/src/utilities/removeDuplicates.d.ts +8 -0
- package/dist/packages/extension-bubble-menu/src/bubble-menu-plugin.d.ts +76 -0
- package/dist/packages/extension-bubble-menu/src/bubble-menu.d.ts +15 -0
- package/dist/packages/extension-bubble-menu/src/index.d.ts +4 -0
- package/dist/packages/extension-floating-menu/src/floating-menu-plugin.d.ts +66 -0
- package/dist/packages/extension-floating-menu/src/floating-menu.d.ts +15 -0
- package/dist/packages/extension-floating-menu/src/index.d.ts +4 -0
- package/dist/packages/react/src/BubbleMenu.d.ts +11 -11
- package/dist/packages/react/src/Context.d.ts +15 -15
- package/dist/packages/react/src/Editor.d.ts +12 -12
- package/dist/packages/react/src/EditorContent.d.ts +24 -24
- package/dist/packages/react/src/FloatingMenu.d.ts +10 -10
- package/dist/packages/react/src/NodeViewContent.d.ts +6 -6
- package/dist/packages/react/src/NodeViewWrapper.d.ts +6 -6
- package/dist/packages/react/src/ReactNodeViewRenderer.d.ts +16 -16
- package/dist/packages/react/src/ReactRenderer.d.ts +62 -62
- package/dist/packages/react/src/index.d.ts +12 -12
- package/dist/packages/react/src/useEditor.d.ts +11 -11
- package/dist/packages/react/src/useReactNodeView.d.ts +7 -7
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,565 +1,558 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var extensionBubbleMenu = require('@tiptap/extension-bubble-menu');
|
|
6
4
|
var React = require('react');
|
|
7
5
|
var ReactDOM = require('react-dom');
|
|
8
6
|
var core = require('@tiptap/core');
|
|
9
7
|
var extensionFloatingMenu = require('@tiptap/extension-floating-menu');
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
editor.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
editor.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
innerRef: ref,
|
|
132
|
-
...props,
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
const EditorContent = React__default["default"].memo(EditorContentWithKey);
|
|
9
|
+
const mergeRefs = (...refs) => {
|
|
10
|
+
return (node) => {
|
|
11
|
+
refs.forEach(ref => {
|
|
12
|
+
if (typeof ref === 'function') {
|
|
13
|
+
ref(node);
|
|
14
|
+
}
|
|
15
|
+
else if (ref) {
|
|
16
|
+
ref.current = node;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
const Portals = ({ renderers }) => {
|
|
22
|
+
return (React.createElement(React.Fragment, null, Object.entries(renderers).map(([key, renderer]) => {
|
|
23
|
+
return ReactDOM.createPortal(renderer.reactElement, renderer.element, key);
|
|
24
|
+
})));
|
|
25
|
+
};
|
|
26
|
+
class PureEditorContent extends React.Component {
|
|
27
|
+
constructor(props) {
|
|
28
|
+
super(props);
|
|
29
|
+
this.editorContentRef = React.createRef();
|
|
30
|
+
this.initialized = false;
|
|
31
|
+
this.state = {
|
|
32
|
+
renderers: {},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
componentDidMount() {
|
|
36
|
+
this.init();
|
|
37
|
+
}
|
|
38
|
+
componentDidUpdate() {
|
|
39
|
+
this.init();
|
|
40
|
+
}
|
|
41
|
+
init() {
|
|
42
|
+
const { editor } = this.props;
|
|
43
|
+
if (editor && !editor.isDestroyed && editor.options.element) {
|
|
44
|
+
if (editor.contentComponent) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const element = this.editorContentRef.current;
|
|
48
|
+
element.append(...editor.options.element.childNodes);
|
|
49
|
+
editor.setOptions({
|
|
50
|
+
element,
|
|
51
|
+
});
|
|
52
|
+
editor.contentComponent = this;
|
|
53
|
+
editor.createNodeViews();
|
|
54
|
+
this.initialized = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
maybeFlushSync(fn) {
|
|
58
|
+
// Avoid calling flushSync until the editor is initialized.
|
|
59
|
+
// Initialization happens during the componentDidMount or componentDidUpdate
|
|
60
|
+
// lifecycle methods, and React doesn't allow calling flushSync from inside
|
|
61
|
+
// a lifecycle method.
|
|
62
|
+
if (this.initialized) {
|
|
63
|
+
ReactDOM.flushSync(fn);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
fn();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
setRenderer(id, renderer) {
|
|
70
|
+
this.maybeFlushSync(() => {
|
|
71
|
+
this.setState(({ renderers }) => ({
|
|
72
|
+
renderers: {
|
|
73
|
+
...renderers,
|
|
74
|
+
[id]: renderer,
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
removeRenderer(id) {
|
|
80
|
+
this.maybeFlushSync(() => {
|
|
81
|
+
this.setState(({ renderers }) => {
|
|
82
|
+
const nextRenderers = { ...renderers };
|
|
83
|
+
delete nextRenderers[id];
|
|
84
|
+
return { renderers: nextRenderers };
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
componentWillUnmount() {
|
|
89
|
+
const { editor } = this.props;
|
|
90
|
+
if (!editor) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.initialized = false;
|
|
94
|
+
if (!editor.isDestroyed) {
|
|
95
|
+
editor.view.setProps({
|
|
96
|
+
nodeViews: {},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
editor.contentComponent = null;
|
|
100
|
+
if (!editor.options.element.firstChild) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const newElement = document.createElement('div');
|
|
104
|
+
newElement.append(...editor.options.element.childNodes);
|
|
105
|
+
editor.setOptions({
|
|
106
|
+
element: newElement,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
render() {
|
|
110
|
+
const { editor, innerRef, ...rest } = this.props;
|
|
111
|
+
return (React.createElement(React.Fragment, null,
|
|
112
|
+
React.createElement("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
|
|
113
|
+
React.createElement(Portals, { renderers: this.state.renderers })));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// EditorContent should be re-created whenever the Editor instance changes
|
|
117
|
+
const EditorContentWithKey = React.forwardRef((props, ref) => {
|
|
118
|
+
const key = React.useMemo(() => {
|
|
119
|
+
return Math.floor(Math.random() * 0xFFFFFFFF).toString();
|
|
120
|
+
}, [props.editor]);
|
|
121
|
+
// Can't use JSX here because it conflicts with the type definition of Vue's JSX, so use createElement
|
|
122
|
+
return React.createElement(PureEditorContent, {
|
|
123
|
+
key,
|
|
124
|
+
innerRef: ref,
|
|
125
|
+
...props,
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
const EditorContent = React.memo(EditorContentWithKey);
|
|
136
129
|
|
|
137
|
-
class Editor extends core.Editor {
|
|
138
|
-
constructor() {
|
|
139
|
-
super(...arguments);
|
|
140
|
-
this.contentComponent = null;
|
|
141
|
-
}
|
|
130
|
+
class Editor extends core.Editor {
|
|
131
|
+
constructor() {
|
|
132
|
+
super(...arguments);
|
|
133
|
+
this.contentComponent = null;
|
|
134
|
+
}
|
|
142
135
|
}
|
|
143
136
|
|
|
144
|
-
/**
|
|
145
|
-
* This hook allows you to create an editor instance.
|
|
146
|
-
* @param options The editor options
|
|
147
|
-
* @param deps The dependencies to watch for changes
|
|
148
|
-
* @returns The editor instance
|
|
149
|
-
* @example const editor = useEditor({ extensions: [...] })
|
|
150
|
-
*/
|
|
151
|
-
const useEditor = (options = {}, deps = []) => {
|
|
152
|
-
const editorRef = React.useRef(null);
|
|
153
|
-
const [, forceUpdate] = React.useState({});
|
|
154
|
-
const { onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, onContentError, } = options;
|
|
155
|
-
const onBeforeCreateRef = React.useRef(onBeforeCreate);
|
|
156
|
-
const onBlurRef = React.useRef(onBlur);
|
|
157
|
-
const onCreateRef = React.useRef(onCreate);
|
|
158
|
-
const onDestroyRef = React.useRef(onDestroy);
|
|
159
|
-
const onFocusRef = React.useRef(onFocus);
|
|
160
|
-
const onSelectionUpdateRef = React.useRef(onSelectionUpdate);
|
|
161
|
-
const onTransactionRef = React.useRef(onTransaction);
|
|
162
|
-
const onUpdateRef = React.useRef(onUpdate);
|
|
163
|
-
const onContentErrorRef = React.useRef(onContentError);
|
|
164
|
-
// This effect will handle updating the editor instance
|
|
165
|
-
// when the event handlers change.
|
|
166
|
-
React.useEffect(() => {
|
|
167
|
-
if (!editorRef.current) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
if (onBeforeCreate) {
|
|
171
|
-
editorRef.current.off('beforeCreate', onBeforeCreateRef.current);
|
|
172
|
-
editorRef.current.on('beforeCreate', onBeforeCreate);
|
|
173
|
-
onBeforeCreateRef.current = onBeforeCreate;
|
|
174
|
-
}
|
|
175
|
-
if (onBlur) {
|
|
176
|
-
editorRef.current.off('blur', onBlurRef.current);
|
|
177
|
-
editorRef.current.on('blur', onBlur);
|
|
178
|
-
onBlurRef.current = onBlur;
|
|
179
|
-
}
|
|
180
|
-
if (onCreate) {
|
|
181
|
-
editorRef.current.off('create', onCreateRef.current);
|
|
182
|
-
editorRef.current.on('create', onCreate);
|
|
183
|
-
onCreateRef.current = onCreate;
|
|
184
|
-
}
|
|
185
|
-
if (onDestroy) {
|
|
186
|
-
editorRef.current.off('destroy', onDestroyRef.current);
|
|
187
|
-
editorRef.current.on('destroy', onDestroy);
|
|
188
|
-
onDestroyRef.current = onDestroy;
|
|
189
|
-
}
|
|
190
|
-
if (onFocus) {
|
|
191
|
-
editorRef.current.off('focus', onFocusRef.current);
|
|
192
|
-
editorRef.current.on('focus', onFocus);
|
|
193
|
-
onFocusRef.current = onFocus;
|
|
194
|
-
}
|
|
195
|
-
if (onSelectionUpdate) {
|
|
196
|
-
editorRef.current.off('selectionUpdate', onSelectionUpdateRef.current);
|
|
197
|
-
editorRef.current.on('selectionUpdate', onSelectionUpdate);
|
|
198
|
-
onSelectionUpdateRef.current = onSelectionUpdate;
|
|
199
|
-
}
|
|
200
|
-
if (onTransaction) {
|
|
201
|
-
editorRef.current.off('transaction', onTransactionRef.current);
|
|
202
|
-
editorRef.current.on('transaction', onTransaction);
|
|
203
|
-
onTransactionRef.current = onTransaction;
|
|
204
|
-
}
|
|
205
|
-
if (onUpdate) {
|
|
206
|
-
editorRef.current.off('update', onUpdateRef.current);
|
|
207
|
-
editorRef.current.on('update', onUpdate);
|
|
208
|
-
onUpdateRef.current = onUpdate;
|
|
209
|
-
}
|
|
210
|
-
if (onContentError) {
|
|
211
|
-
editorRef.current.off('contentError', onContentErrorRef.current);
|
|
212
|
-
editorRef.current.on('contentError', onContentError);
|
|
213
|
-
onContentErrorRef.current = onContentError;
|
|
214
|
-
}
|
|
215
|
-
}, [onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, editorRef.current]);
|
|
216
|
-
React.useEffect(() => {
|
|
217
|
-
let isMounted = true;
|
|
218
|
-
const editor = new Editor(options);
|
|
219
|
-
editorRef.current = editor;
|
|
220
|
-
editorRef.current.on('transaction', () => {
|
|
221
|
-
requestAnimationFrame(() => {
|
|
222
|
-
requestAnimationFrame(() => {
|
|
223
|
-
if (isMounted) {
|
|
224
|
-
forceUpdate({});
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
return () => {
|
|
230
|
-
isMounted = false;
|
|
231
|
-
editor.destroy();
|
|
232
|
-
};
|
|
233
|
-
}, deps);
|
|
234
|
-
return editorRef.current;
|
|
137
|
+
/**
|
|
138
|
+
* This hook allows you to create an editor instance.
|
|
139
|
+
* @param options The editor options
|
|
140
|
+
* @param deps The dependencies to watch for changes
|
|
141
|
+
* @returns The editor instance
|
|
142
|
+
* @example const editor = useEditor({ extensions: [...] })
|
|
143
|
+
*/
|
|
144
|
+
const useEditor = (options = {}, deps = []) => {
|
|
145
|
+
const editorRef = React.useRef(null);
|
|
146
|
+
const [, forceUpdate] = React.useState({});
|
|
147
|
+
const { onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, onContentError, } = options;
|
|
148
|
+
const onBeforeCreateRef = React.useRef(onBeforeCreate);
|
|
149
|
+
const onBlurRef = React.useRef(onBlur);
|
|
150
|
+
const onCreateRef = React.useRef(onCreate);
|
|
151
|
+
const onDestroyRef = React.useRef(onDestroy);
|
|
152
|
+
const onFocusRef = React.useRef(onFocus);
|
|
153
|
+
const onSelectionUpdateRef = React.useRef(onSelectionUpdate);
|
|
154
|
+
const onTransactionRef = React.useRef(onTransaction);
|
|
155
|
+
const onUpdateRef = React.useRef(onUpdate);
|
|
156
|
+
const onContentErrorRef = React.useRef(onContentError);
|
|
157
|
+
// This effect will handle updating the editor instance
|
|
158
|
+
// when the event handlers change.
|
|
159
|
+
React.useEffect(() => {
|
|
160
|
+
if (!editorRef.current) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (onBeforeCreate) {
|
|
164
|
+
editorRef.current.off('beforeCreate', onBeforeCreateRef.current);
|
|
165
|
+
editorRef.current.on('beforeCreate', onBeforeCreate);
|
|
166
|
+
onBeforeCreateRef.current = onBeforeCreate;
|
|
167
|
+
}
|
|
168
|
+
if (onBlur) {
|
|
169
|
+
editorRef.current.off('blur', onBlurRef.current);
|
|
170
|
+
editorRef.current.on('blur', onBlur);
|
|
171
|
+
onBlurRef.current = onBlur;
|
|
172
|
+
}
|
|
173
|
+
if (onCreate) {
|
|
174
|
+
editorRef.current.off('create', onCreateRef.current);
|
|
175
|
+
editorRef.current.on('create', onCreate);
|
|
176
|
+
onCreateRef.current = onCreate;
|
|
177
|
+
}
|
|
178
|
+
if (onDestroy) {
|
|
179
|
+
editorRef.current.off('destroy', onDestroyRef.current);
|
|
180
|
+
editorRef.current.on('destroy', onDestroy);
|
|
181
|
+
onDestroyRef.current = onDestroy;
|
|
182
|
+
}
|
|
183
|
+
if (onFocus) {
|
|
184
|
+
editorRef.current.off('focus', onFocusRef.current);
|
|
185
|
+
editorRef.current.on('focus', onFocus);
|
|
186
|
+
onFocusRef.current = onFocus;
|
|
187
|
+
}
|
|
188
|
+
if (onSelectionUpdate) {
|
|
189
|
+
editorRef.current.off('selectionUpdate', onSelectionUpdateRef.current);
|
|
190
|
+
editorRef.current.on('selectionUpdate', onSelectionUpdate);
|
|
191
|
+
onSelectionUpdateRef.current = onSelectionUpdate;
|
|
192
|
+
}
|
|
193
|
+
if (onTransaction) {
|
|
194
|
+
editorRef.current.off('transaction', onTransactionRef.current);
|
|
195
|
+
editorRef.current.on('transaction', onTransaction);
|
|
196
|
+
onTransactionRef.current = onTransaction;
|
|
197
|
+
}
|
|
198
|
+
if (onUpdate) {
|
|
199
|
+
editorRef.current.off('update', onUpdateRef.current);
|
|
200
|
+
editorRef.current.on('update', onUpdate);
|
|
201
|
+
onUpdateRef.current = onUpdate;
|
|
202
|
+
}
|
|
203
|
+
if (onContentError) {
|
|
204
|
+
editorRef.current.off('contentError', onContentErrorRef.current);
|
|
205
|
+
editorRef.current.on('contentError', onContentError);
|
|
206
|
+
onContentErrorRef.current = onContentError;
|
|
207
|
+
}
|
|
208
|
+
}, [onBeforeCreate, onBlur, onCreate, onDestroy, onFocus, onSelectionUpdate, onTransaction, onUpdate, editorRef.current]);
|
|
209
|
+
React.useEffect(() => {
|
|
210
|
+
let isMounted = true;
|
|
211
|
+
const editor = new Editor(options);
|
|
212
|
+
editorRef.current = editor;
|
|
213
|
+
editorRef.current.on('transaction', () => {
|
|
214
|
+
requestAnimationFrame(() => {
|
|
215
|
+
requestAnimationFrame(() => {
|
|
216
|
+
if (isMounted) {
|
|
217
|
+
forceUpdate({});
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
return () => {
|
|
223
|
+
isMounted = false;
|
|
224
|
+
editor.destroy();
|
|
225
|
+
};
|
|
226
|
+
}, deps);
|
|
227
|
+
return editorRef.current;
|
|
235
228
|
};
|
|
236
229
|
|
|
237
|
-
const EditorContext = React.createContext({
|
|
238
|
-
editor: null,
|
|
239
|
-
});
|
|
240
|
-
const EditorConsumer = EditorContext.Consumer;
|
|
241
|
-
const useCurrentEditor = () => React.useContext(EditorContext);
|
|
242
|
-
const EditorProvider = ({ children, slotAfter, slotBefore, ...editorOptions }) => {
|
|
243
|
-
const editor = useEditor(editorOptions);
|
|
244
|
-
if (!editor) {
|
|
245
|
-
return null;
|
|
246
|
-
}
|
|
247
|
-
return (
|
|
248
|
-
slotBefore,
|
|
249
|
-
|
|
250
|
-
children,
|
|
251
|
-
slotAfter));
|
|
230
|
+
const EditorContext = React.createContext({
|
|
231
|
+
editor: null,
|
|
232
|
+
});
|
|
233
|
+
const EditorConsumer = EditorContext.Consumer;
|
|
234
|
+
const useCurrentEditor = () => React.useContext(EditorContext);
|
|
235
|
+
const EditorProvider = ({ children, slotAfter, slotBefore, ...editorOptions }) => {
|
|
236
|
+
const editor = useEditor(editorOptions);
|
|
237
|
+
if (!editor) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
return (React.createElement(EditorContext.Provider, { value: { editor } },
|
|
241
|
+
slotBefore,
|
|
242
|
+
React.createElement(EditorConsumer, null, ({ editor: currentEditor }) => (React.createElement(EditorContent, { editor: currentEditor }))),
|
|
243
|
+
children,
|
|
244
|
+
slotAfter));
|
|
252
245
|
};
|
|
253
246
|
|
|
254
|
-
const BubbleMenu = (props) => {
|
|
255
|
-
const [element, setElement] = React.useState(null);
|
|
256
|
-
const { editor: currentEditor } = useCurrentEditor();
|
|
257
|
-
React.useEffect(() => {
|
|
258
|
-
var _a;
|
|
259
|
-
if (!element) {
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
const { pluginKey = 'bubbleMenu', editor, tippyOptions = {}, updateDelay, shouldShow = null, } = props;
|
|
266
|
-
const menuEditor = editor || currentEditor;
|
|
267
|
-
if (!menuEditor) {
|
|
268
|
-
console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.');
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
const plugin = extensionBubbleMenu.BubbleMenuPlugin({
|
|
272
|
-
updateDelay,
|
|
273
|
-
editor: menuEditor,
|
|
274
|
-
element,
|
|
275
|
-
pluginKey,
|
|
276
|
-
shouldShow,
|
|
277
|
-
tippyOptions,
|
|
278
|
-
});
|
|
279
|
-
menuEditor.registerPlugin(plugin);
|
|
280
|
-
return () => menuEditor.unregisterPlugin(pluginKey);
|
|
281
|
-
}, [props.editor, currentEditor, element]);
|
|
282
|
-
return (
|
|
247
|
+
const BubbleMenu = (props) => {
|
|
248
|
+
const [element, setElement] = React.useState(null);
|
|
249
|
+
const { editor: currentEditor } = useCurrentEditor();
|
|
250
|
+
React.useEffect(() => {
|
|
251
|
+
var _a;
|
|
252
|
+
if (!element) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const { pluginKey = 'bubbleMenu', editor, tippyOptions = {}, updateDelay, shouldShow = null, } = props;
|
|
259
|
+
const menuEditor = editor || currentEditor;
|
|
260
|
+
if (!menuEditor) {
|
|
261
|
+
console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const plugin = extensionBubbleMenu.BubbleMenuPlugin({
|
|
265
|
+
updateDelay,
|
|
266
|
+
editor: menuEditor,
|
|
267
|
+
element,
|
|
268
|
+
pluginKey,
|
|
269
|
+
shouldShow,
|
|
270
|
+
tippyOptions,
|
|
271
|
+
});
|
|
272
|
+
menuEditor.registerPlugin(plugin);
|
|
273
|
+
return () => menuEditor.unregisterPlugin(pluginKey);
|
|
274
|
+
}, [props.editor, currentEditor, element]);
|
|
275
|
+
return (React.createElement("div", { ref: setElement, className: props.className, style: { visibility: 'hidden' } }, props.children));
|
|
283
276
|
};
|
|
284
277
|
|
|
285
|
-
const FloatingMenu = (props) => {
|
|
286
|
-
const [element, setElement] = React.useState(null);
|
|
287
|
-
const { editor: currentEditor } = useCurrentEditor();
|
|
288
|
-
React.useEffect(() => {
|
|
289
|
-
var _a;
|
|
290
|
-
if (!element) {
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
const { pluginKey = 'floatingMenu', editor, tippyOptions = {}, shouldShow = null, } = props;
|
|
297
|
-
const menuEditor = editor || currentEditor;
|
|
298
|
-
if (!menuEditor) {
|
|
299
|
-
console.warn('FloatingMenu component is not rendered inside of an editor component or does not have editor prop.');
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const plugin = extensionFloatingMenu.FloatingMenuPlugin({
|
|
303
|
-
pluginKey,
|
|
304
|
-
editor: menuEditor,
|
|
305
|
-
element,
|
|
306
|
-
tippyOptions,
|
|
307
|
-
shouldShow,
|
|
308
|
-
});
|
|
309
|
-
menuEditor.registerPlugin(plugin);
|
|
310
|
-
return () => menuEditor.unregisterPlugin(pluginKey);
|
|
311
|
-
}, [
|
|
312
|
-
props.editor,
|
|
313
|
-
currentEditor,
|
|
314
|
-
element,
|
|
315
|
-
]);
|
|
316
|
-
return (
|
|
278
|
+
const FloatingMenu = (props) => {
|
|
279
|
+
const [element, setElement] = React.useState(null);
|
|
280
|
+
const { editor: currentEditor } = useCurrentEditor();
|
|
281
|
+
React.useEffect(() => {
|
|
282
|
+
var _a;
|
|
283
|
+
if (!element) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const { pluginKey = 'floatingMenu', editor, tippyOptions = {}, shouldShow = null, } = props;
|
|
290
|
+
const menuEditor = editor || currentEditor;
|
|
291
|
+
if (!menuEditor) {
|
|
292
|
+
console.warn('FloatingMenu component is not rendered inside of an editor component or does not have editor prop.');
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const plugin = extensionFloatingMenu.FloatingMenuPlugin({
|
|
296
|
+
pluginKey,
|
|
297
|
+
editor: menuEditor,
|
|
298
|
+
element,
|
|
299
|
+
tippyOptions,
|
|
300
|
+
shouldShow,
|
|
301
|
+
});
|
|
302
|
+
menuEditor.registerPlugin(plugin);
|
|
303
|
+
return () => menuEditor.unregisterPlugin(pluginKey);
|
|
304
|
+
}, [
|
|
305
|
+
props.editor,
|
|
306
|
+
currentEditor,
|
|
307
|
+
element,
|
|
308
|
+
]);
|
|
309
|
+
return (React.createElement("div", { ref: setElement, className: props.className, style: { visibility: 'hidden' } }, props.children));
|
|
317
310
|
};
|
|
318
311
|
|
|
319
|
-
const ReactNodeViewContext = React.createContext({
|
|
320
|
-
onDragStart: undefined,
|
|
321
|
-
});
|
|
312
|
+
const ReactNodeViewContext = React.createContext({
|
|
313
|
+
onDragStart: undefined,
|
|
314
|
+
});
|
|
322
315
|
const useReactNodeView = () => React.useContext(ReactNodeViewContext);
|
|
323
316
|
|
|
324
|
-
const NodeViewContent = props => {
|
|
325
|
-
const Tag = props.as || 'div';
|
|
326
|
-
const { nodeViewContentRef } = useReactNodeView();
|
|
327
|
-
return (
|
|
328
|
-
whiteSpace: 'pre-wrap',
|
|
329
|
-
...props.style,
|
|
330
|
-
} }));
|
|
317
|
+
const NodeViewContent = props => {
|
|
318
|
+
const Tag = props.as || 'div';
|
|
319
|
+
const { nodeViewContentRef } = useReactNodeView();
|
|
320
|
+
return (React.createElement(Tag, { ...props, ref: nodeViewContentRef, "data-node-view-content": "", style: {
|
|
321
|
+
whiteSpace: 'pre-wrap',
|
|
322
|
+
...props.style,
|
|
323
|
+
} }));
|
|
331
324
|
};
|
|
332
325
|
|
|
333
|
-
const NodeViewWrapper =
|
|
334
|
-
const { onDragStart } = useReactNodeView();
|
|
335
|
-
const Tag = props.as || 'div';
|
|
336
|
-
return (
|
|
337
|
-
whiteSpace: 'normal',
|
|
338
|
-
...props.style,
|
|
339
|
-
} }));
|
|
326
|
+
const NodeViewWrapper = React.forwardRef((props, ref) => {
|
|
327
|
+
const { onDragStart } = useReactNodeView();
|
|
328
|
+
const Tag = props.as || 'div';
|
|
329
|
+
return (React.createElement(Tag, { ...props, ref: ref, "data-node-view-wrapper": "", onDragStart: onDragStart, style: {
|
|
330
|
+
whiteSpace: 'normal',
|
|
331
|
+
...props.style,
|
|
332
|
+
} }));
|
|
340
333
|
});
|
|
341
334
|
|
|
342
|
-
/**
|
|
343
|
-
* Check if a component is a class component.
|
|
344
|
-
* @param Component
|
|
345
|
-
* @returns {boolean}
|
|
346
|
-
*/
|
|
347
|
-
function isClassComponent(Component) {
|
|
348
|
-
return !!(typeof Component === 'function'
|
|
349
|
-
&& Component.prototype
|
|
350
|
-
&& Component.prototype.isReactComponent);
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Check if a component is a forward ref component.
|
|
354
|
-
* @param Component
|
|
355
|
-
* @returns {boolean}
|
|
356
|
-
*/
|
|
357
|
-
function isForwardRefComponent(Component) {
|
|
358
|
-
var _a;
|
|
359
|
-
return !!(typeof Component === 'object'
|
|
360
|
-
&& ((_a = Component.$$typeof) === null || _a === void 0 ? void 0 : _a.toString()) === 'Symbol(react.forward_ref)');
|
|
361
|
-
}
|
|
362
|
-
/**
|
|
363
|
-
* The ReactRenderer class. It's responsible for rendering React components inside the editor.
|
|
364
|
-
* @example
|
|
365
|
-
* new ReactRenderer(MyComponent, {
|
|
366
|
-
* editor,
|
|
367
|
-
* props: {
|
|
368
|
-
* foo: 'bar',
|
|
369
|
-
* },
|
|
370
|
-
* as: 'span',
|
|
371
|
-
* })
|
|
372
|
-
*/
|
|
373
|
-
class ReactRenderer {
|
|
374
|
-
constructor(component, { editor, props = {}, as = 'div', className = '', attrs, }) {
|
|
375
|
-
this.ref = null;
|
|
376
|
-
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString();
|
|
377
|
-
this.component = component;
|
|
378
|
-
this.editor = editor;
|
|
379
|
-
this.props = props;
|
|
380
|
-
this.element = document.createElement(as);
|
|
381
|
-
this.element.classList.add('react-renderer');
|
|
382
|
-
if (className) {
|
|
383
|
-
this.element.classList.add(...className.split(' '));
|
|
384
|
-
}
|
|
385
|
-
if (attrs) {
|
|
386
|
-
Object.keys(attrs).forEach(key => {
|
|
387
|
-
this.element.setAttribute(key, attrs[key]);
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
this.render();
|
|
391
|
-
}
|
|
392
|
-
render() {
|
|
393
|
-
var _a, _b;
|
|
394
|
-
const Component = this.component;
|
|
395
|
-
const props = this.props;
|
|
396
|
-
if (isClassComponent(Component) || isForwardRefComponent(Component)) {
|
|
397
|
-
props.ref = (ref) => {
|
|
398
|
-
this.ref = ref;
|
|
399
|
-
};
|
|
400
|
-
}
|
|
401
|
-
this.reactElement =
|
|
402
|
-
(_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.contentComponent) === null || _b === void 0 ? void 0 : _b.setRenderer(this.id, this);
|
|
403
|
-
}
|
|
404
|
-
updateProps(props = {}) {
|
|
405
|
-
this.props = {
|
|
406
|
-
...this.props,
|
|
407
|
-
...props,
|
|
408
|
-
};
|
|
409
|
-
this.render();
|
|
410
|
-
}
|
|
411
|
-
destroy() {
|
|
412
|
-
var _a, _b;
|
|
413
|
-
(_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.contentComponent) === null || _b === void 0 ? void 0 : _b.removeRenderer(this.id);
|
|
414
|
-
}
|
|
335
|
+
/**
|
|
336
|
+
* Check if a component is a class component.
|
|
337
|
+
* @param Component
|
|
338
|
+
* @returns {boolean}
|
|
339
|
+
*/
|
|
340
|
+
function isClassComponent(Component) {
|
|
341
|
+
return !!(typeof Component === 'function'
|
|
342
|
+
&& Component.prototype
|
|
343
|
+
&& Component.prototype.isReactComponent);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Check if a component is a forward ref component.
|
|
347
|
+
* @param Component
|
|
348
|
+
* @returns {boolean}
|
|
349
|
+
*/
|
|
350
|
+
function isForwardRefComponent(Component) {
|
|
351
|
+
var _a;
|
|
352
|
+
return !!(typeof Component === 'object'
|
|
353
|
+
&& ((_a = Component.$$typeof) === null || _a === void 0 ? void 0 : _a.toString()) === 'Symbol(react.forward_ref)');
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The ReactRenderer class. It's responsible for rendering React components inside the editor.
|
|
357
|
+
* @example
|
|
358
|
+
* new ReactRenderer(MyComponent, {
|
|
359
|
+
* editor,
|
|
360
|
+
* props: {
|
|
361
|
+
* foo: 'bar',
|
|
362
|
+
* },
|
|
363
|
+
* as: 'span',
|
|
364
|
+
* })
|
|
365
|
+
*/
|
|
366
|
+
class ReactRenderer {
|
|
367
|
+
constructor(component, { editor, props = {}, as = 'div', className = '', attrs, }) {
|
|
368
|
+
this.ref = null;
|
|
369
|
+
this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString();
|
|
370
|
+
this.component = component;
|
|
371
|
+
this.editor = editor;
|
|
372
|
+
this.props = props;
|
|
373
|
+
this.element = document.createElement(as);
|
|
374
|
+
this.element.classList.add('react-renderer');
|
|
375
|
+
if (className) {
|
|
376
|
+
this.element.classList.add(...className.split(' '));
|
|
377
|
+
}
|
|
378
|
+
if (attrs) {
|
|
379
|
+
Object.keys(attrs).forEach(key => {
|
|
380
|
+
this.element.setAttribute(key, attrs[key]);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
this.render();
|
|
384
|
+
}
|
|
385
|
+
render() {
|
|
386
|
+
var _a, _b;
|
|
387
|
+
const Component = this.component;
|
|
388
|
+
const props = this.props;
|
|
389
|
+
if (isClassComponent(Component) || isForwardRefComponent(Component)) {
|
|
390
|
+
props.ref = (ref) => {
|
|
391
|
+
this.ref = ref;
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
this.reactElement = React.createElement(Component, { ...props });
|
|
395
|
+
(_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.contentComponent) === null || _b === void 0 ? void 0 : _b.setRenderer(this.id, this);
|
|
396
|
+
}
|
|
397
|
+
updateProps(props = {}) {
|
|
398
|
+
this.props = {
|
|
399
|
+
...this.props,
|
|
400
|
+
...props,
|
|
401
|
+
};
|
|
402
|
+
this.render();
|
|
403
|
+
}
|
|
404
|
+
destroy() {
|
|
405
|
+
var _a, _b;
|
|
406
|
+
(_b = (_a = this.editor) === null || _a === void 0 ? void 0 : _a.contentComponent) === null || _b === void 0 ? void 0 : _b.removeRenderer(this.id);
|
|
407
|
+
}
|
|
415
408
|
}
|
|
416
409
|
|
|
417
|
-
class ReactNodeView extends core.NodeView {
|
|
418
|
-
mount() {
|
|
419
|
-
const props = {
|
|
420
|
-
editor: this.editor,
|
|
421
|
-
node: this.node,
|
|
422
|
-
decorations: this.decorations,
|
|
423
|
-
selected: false,
|
|
424
|
-
extension: this.extension,
|
|
425
|
-
getPos: () => this.getPos(),
|
|
426
|
-
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
427
|
-
deleteNode: () => this.deleteNode(),
|
|
428
|
-
};
|
|
429
|
-
if (!this.component.displayName) {
|
|
430
|
-
const capitalizeFirstChar = (string) => {
|
|
431
|
-
return string.charAt(0).toUpperCase() + string.substring(1);
|
|
432
|
-
};
|
|
433
|
-
this.component.displayName = capitalizeFirstChar(this.extension.name);
|
|
434
|
-
}
|
|
435
|
-
const ReactNodeViewProvider = componentProps => {
|
|
436
|
-
const Component = this.component;
|
|
437
|
-
const onDragStart = this.onDragStart.bind(this);
|
|
438
|
-
const nodeViewContentRef = element => {
|
|
439
|
-
if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
|
|
440
|
-
element.appendChild(this.contentDOMElement);
|
|
441
|
-
}
|
|
442
|
-
};
|
|
443
|
-
return (
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
};
|
|
447
|
-
ReactNodeViewProvider.displayName = 'ReactNodeView';
|
|
448
|
-
if (this.node.isLeaf) {
|
|
449
|
-
this.contentDOMElement = null;
|
|
450
|
-
}
|
|
451
|
-
else if (this.options.contentDOMElementTag) {
|
|
452
|
-
this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
|
|
453
|
-
}
|
|
454
|
-
else {
|
|
455
|
-
this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div');
|
|
456
|
-
}
|
|
457
|
-
if (this.contentDOMElement) {
|
|
458
|
-
// For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
|
|
459
|
-
// With this fix it seems to work fine
|
|
460
|
-
// See: https://github.com/ueberdosis/tiptap/issues/1197
|
|
461
|
-
this.contentDOMElement.style.whiteSpace = 'inherit';
|
|
462
|
-
}
|
|
463
|
-
let as = this.node.isInline ? 'span' : 'div';
|
|
464
|
-
if (this.options.as) {
|
|
465
|
-
as = this.options.as;
|
|
466
|
-
}
|
|
467
|
-
const { className = '' } = this.options;
|
|
468
|
-
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
469
|
-
this.editor.on('selectionUpdate', this.handleSelectionUpdate);
|
|
470
|
-
this.renderer = new ReactRenderer(ReactNodeViewProvider, {
|
|
471
|
-
editor: this.editor,
|
|
472
|
-
props,
|
|
473
|
-
as,
|
|
474
|
-
className: `node-${this.node.type.name} ${className}`.trim(),
|
|
475
|
-
attrs: this.options.attrs,
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
get dom() {
|
|
479
|
-
var _a;
|
|
480
|
-
if (this.renderer.element.firstElementChild
|
|
481
|
-
&& !((_a = this.renderer.element.firstElementChild) === null || _a === void 0 ? void 0 : _a.hasAttribute('data-node-view-wrapper'))) {
|
|
482
|
-
throw Error('Please use the NodeViewWrapper component for your node view.');
|
|
483
|
-
}
|
|
484
|
-
return this.renderer.element;
|
|
485
|
-
}
|
|
486
|
-
get contentDOM() {
|
|
487
|
-
if (this.node.isLeaf) {
|
|
488
|
-
return null;
|
|
489
|
-
}
|
|
490
|
-
return this.contentDOMElement;
|
|
491
|
-
}
|
|
492
|
-
handleSelectionUpdate() {
|
|
493
|
-
const { from, to } = this.editor.state.selection;
|
|
494
|
-
if (from <= this.getPos() && to >= this.getPos() + this.node.nodeSize) {
|
|
495
|
-
if (this.renderer.props.selected) {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
this.selectNode();
|
|
499
|
-
}
|
|
500
|
-
else {
|
|
501
|
-
if (!this.renderer.props.selected) {
|
|
502
|
-
return;
|
|
503
|
-
}
|
|
504
|
-
this.deselectNode();
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
update(node, decorations) {
|
|
508
|
-
const updateProps = (props) => {
|
|
509
|
-
this.renderer.updateProps(props);
|
|
510
|
-
};
|
|
511
|
-
if (node.type !== this.node.type) {
|
|
512
|
-
return false;
|
|
513
|
-
}
|
|
514
|
-
if (typeof this.options.update === 'function') {
|
|
515
|
-
const oldNode = this.node;
|
|
516
|
-
const oldDecorations = this.decorations;
|
|
517
|
-
this.node = node;
|
|
518
|
-
this.decorations = decorations;
|
|
519
|
-
return this.options.update({
|
|
520
|
-
oldNode,
|
|
521
|
-
oldDecorations,
|
|
522
|
-
newNode: node,
|
|
523
|
-
newDecorations: decorations,
|
|
524
|
-
updateProps: () => updateProps({ node, decorations }),
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
if (node === this.node && this.decorations === decorations) {
|
|
528
|
-
return true;
|
|
529
|
-
}
|
|
530
|
-
this.node = node;
|
|
531
|
-
this.decorations = decorations;
|
|
532
|
-
updateProps({ node, decorations });
|
|
533
|
-
return true;
|
|
534
|
-
}
|
|
535
|
-
selectNode() {
|
|
536
|
-
this.renderer.updateProps({
|
|
537
|
-
selected: true,
|
|
538
|
-
});
|
|
539
|
-
this.renderer.element.classList.add('ProseMirror-selectednode');
|
|
540
|
-
}
|
|
541
|
-
deselectNode() {
|
|
542
|
-
this.renderer.updateProps({
|
|
543
|
-
selected: false,
|
|
544
|
-
});
|
|
545
|
-
this.renderer.element.classList.remove('ProseMirror-selectednode');
|
|
546
|
-
}
|
|
547
|
-
destroy() {
|
|
548
|
-
this.renderer.destroy();
|
|
549
|
-
this.editor.off('selectionUpdate', this.handleSelectionUpdate);
|
|
550
|
-
this.contentDOMElement = null;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
function ReactNodeViewRenderer(component, options) {
|
|
554
|
-
return (props) => {
|
|
555
|
-
// try to get the parent component
|
|
556
|
-
// this is important for vue devtools to show the component hierarchy correctly
|
|
557
|
-
// maybe it’s `undefined` because <editor-content> isn’t rendered yet
|
|
558
|
-
if (!props.editor.contentComponent) {
|
|
559
|
-
return {};
|
|
560
|
-
}
|
|
561
|
-
return new ReactNodeView(component, props, options);
|
|
562
|
-
};
|
|
410
|
+
class ReactNodeView extends core.NodeView {
|
|
411
|
+
mount() {
|
|
412
|
+
const props = {
|
|
413
|
+
editor: this.editor,
|
|
414
|
+
node: this.node,
|
|
415
|
+
decorations: this.decorations,
|
|
416
|
+
selected: false,
|
|
417
|
+
extension: this.extension,
|
|
418
|
+
getPos: () => this.getPos(),
|
|
419
|
+
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
420
|
+
deleteNode: () => this.deleteNode(),
|
|
421
|
+
};
|
|
422
|
+
if (!this.component.displayName) {
|
|
423
|
+
const capitalizeFirstChar = (string) => {
|
|
424
|
+
return string.charAt(0).toUpperCase() + string.substring(1);
|
|
425
|
+
};
|
|
426
|
+
this.component.displayName = capitalizeFirstChar(this.extension.name);
|
|
427
|
+
}
|
|
428
|
+
const ReactNodeViewProvider = componentProps => {
|
|
429
|
+
const Component = this.component;
|
|
430
|
+
const onDragStart = this.onDragStart.bind(this);
|
|
431
|
+
const nodeViewContentRef = element => {
|
|
432
|
+
if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
|
|
433
|
+
element.appendChild(this.contentDOMElement);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
return (React.createElement(React.Fragment, null,
|
|
437
|
+
React.createElement(ReactNodeViewContext.Provider, { value: { onDragStart, nodeViewContentRef } },
|
|
438
|
+
React.createElement(Component, { ...componentProps }))));
|
|
439
|
+
};
|
|
440
|
+
ReactNodeViewProvider.displayName = 'ReactNodeView';
|
|
441
|
+
if (this.node.isLeaf) {
|
|
442
|
+
this.contentDOMElement = null;
|
|
443
|
+
}
|
|
444
|
+
else if (this.options.contentDOMElementTag) {
|
|
445
|
+
this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div');
|
|
449
|
+
}
|
|
450
|
+
if (this.contentDOMElement) {
|
|
451
|
+
// For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
|
|
452
|
+
// With this fix it seems to work fine
|
|
453
|
+
// See: https://github.com/ueberdosis/tiptap/issues/1197
|
|
454
|
+
this.contentDOMElement.style.whiteSpace = 'inherit';
|
|
455
|
+
}
|
|
456
|
+
let as = this.node.isInline ? 'span' : 'div';
|
|
457
|
+
if (this.options.as) {
|
|
458
|
+
as = this.options.as;
|
|
459
|
+
}
|
|
460
|
+
const { className = '' } = this.options;
|
|
461
|
+
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
462
|
+
this.editor.on('selectionUpdate', this.handleSelectionUpdate);
|
|
463
|
+
this.renderer = new ReactRenderer(ReactNodeViewProvider, {
|
|
464
|
+
editor: this.editor,
|
|
465
|
+
props,
|
|
466
|
+
as,
|
|
467
|
+
className: `node-${this.node.type.name} ${className}`.trim(),
|
|
468
|
+
attrs: this.options.attrs,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
get dom() {
|
|
472
|
+
var _a;
|
|
473
|
+
if (this.renderer.element.firstElementChild
|
|
474
|
+
&& !((_a = this.renderer.element.firstElementChild) === null || _a === void 0 ? void 0 : _a.hasAttribute('data-node-view-wrapper'))) {
|
|
475
|
+
throw Error('Please use the NodeViewWrapper component for your node view.');
|
|
476
|
+
}
|
|
477
|
+
return this.renderer.element;
|
|
478
|
+
}
|
|
479
|
+
get contentDOM() {
|
|
480
|
+
if (this.node.isLeaf) {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
return this.contentDOMElement;
|
|
484
|
+
}
|
|
485
|
+
handleSelectionUpdate() {
|
|
486
|
+
const { from, to } = this.editor.state.selection;
|
|
487
|
+
if (from <= this.getPos() && to >= this.getPos() + this.node.nodeSize) {
|
|
488
|
+
if (this.renderer.props.selected) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
this.selectNode();
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
if (!this.renderer.props.selected) {
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
this.deselectNode();
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
update(node, decorations) {
|
|
501
|
+
const updateProps = (props) => {
|
|
502
|
+
this.renderer.updateProps(props);
|
|
503
|
+
};
|
|
504
|
+
if (node.type !== this.node.type) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
if (typeof this.options.update === 'function') {
|
|
508
|
+
const oldNode = this.node;
|
|
509
|
+
const oldDecorations = this.decorations;
|
|
510
|
+
this.node = node;
|
|
511
|
+
this.decorations = decorations;
|
|
512
|
+
return this.options.update({
|
|
513
|
+
oldNode,
|
|
514
|
+
oldDecorations,
|
|
515
|
+
newNode: node,
|
|
516
|
+
newDecorations: decorations,
|
|
517
|
+
updateProps: () => updateProps({ node, decorations }),
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
if (node === this.node && this.decorations === decorations) {
|
|
521
|
+
return true;
|
|
522
|
+
}
|
|
523
|
+
this.node = node;
|
|
524
|
+
this.decorations = decorations;
|
|
525
|
+
updateProps({ node, decorations });
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
selectNode() {
|
|
529
|
+
this.renderer.updateProps({
|
|
530
|
+
selected: true,
|
|
531
|
+
});
|
|
532
|
+
this.renderer.element.classList.add('ProseMirror-selectednode');
|
|
533
|
+
}
|
|
534
|
+
deselectNode() {
|
|
535
|
+
this.renderer.updateProps({
|
|
536
|
+
selected: false,
|
|
537
|
+
});
|
|
538
|
+
this.renderer.element.classList.remove('ProseMirror-selectednode');
|
|
539
|
+
}
|
|
540
|
+
destroy() {
|
|
541
|
+
this.renderer.destroy();
|
|
542
|
+
this.editor.off('selectionUpdate', this.handleSelectionUpdate);
|
|
543
|
+
this.contentDOMElement = null;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function ReactNodeViewRenderer(component, options) {
|
|
547
|
+
return (props) => {
|
|
548
|
+
// try to get the parent component
|
|
549
|
+
// this is important for vue devtools to show the component hierarchy correctly
|
|
550
|
+
// maybe it’s `undefined` because <editor-content> isn’t rendered yet
|
|
551
|
+
if (!props.editor.contentComponent) {
|
|
552
|
+
return {};
|
|
553
|
+
}
|
|
554
|
+
return new ReactNodeView(component, props, options);
|
|
555
|
+
};
|
|
563
556
|
}
|
|
564
557
|
|
|
565
558
|
exports.BubbleMenu = BubbleMenu;
|
|
@@ -579,7 +572,7 @@ exports.useCurrentEditor = useCurrentEditor;
|
|
|
579
572
|
exports.useEditor = useEditor;
|
|
580
573
|
exports.useReactNodeView = useReactNodeView;
|
|
581
574
|
Object.keys(core).forEach(function (k) {
|
|
582
|
-
if (k !== 'default' && !
|
|
575
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
583
576
|
enumerable: true,
|
|
584
577
|
get: function () { return core[k]; }
|
|
585
578
|
});
|