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