@tiptap/react 3.7.2 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/menus/index.cjs +24 -28
- package/dist/menus/index.cjs.map +1 -1
- package/dist/menus/index.js +24 -28
- package/dist/menus/index.js.map +1 -1
- package/package.json +7 -7
- package/src/menus/BubbleMenu.tsx +37 -29
package/dist/menus/index.cjs
CHANGED
|
@@ -61,49 +61,45 @@ var BubbleMenu = import_react2.default.forwardRef(
|
|
|
61
61
|
ref.current = menuEl.current;
|
|
62
62
|
}
|
|
63
63
|
const { editor: currentEditor } = (0, import_react.useCurrentEditor)();
|
|
64
|
+
const pluginEditor = editor || currentEditor;
|
|
65
|
+
const bubbleMenuPluginProps = {
|
|
66
|
+
updateDelay,
|
|
67
|
+
resizeDelay,
|
|
68
|
+
appendTo,
|
|
69
|
+
pluginKey,
|
|
70
|
+
shouldShow,
|
|
71
|
+
getReferencedVirtualElement,
|
|
72
|
+
options
|
|
73
|
+
};
|
|
74
|
+
const bubbleMenuPluginPropsRef = (0, import_react2.useRef)(bubbleMenuPluginProps);
|
|
75
|
+
bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps;
|
|
64
76
|
(0, import_react2.useEffect)(() => {
|
|
65
|
-
|
|
66
|
-
bubbleMenuElement.style.visibility = "hidden";
|
|
67
|
-
bubbleMenuElement.style.position = "absolute";
|
|
68
|
-
if ((editor == null ? void 0 : editor.isDestroyed) || (currentEditor == null ? void 0 : currentEditor.isDestroyed)) {
|
|
77
|
+
if (pluginEditor == null ? void 0 : pluginEditor.isDestroyed) {
|
|
69
78
|
return;
|
|
70
79
|
}
|
|
71
|
-
|
|
72
|
-
if (!attachToEditor) {
|
|
80
|
+
if (!pluginEditor) {
|
|
73
81
|
console.warn("BubbleMenu component is not rendered inside of an editor component or does not have editor prop.");
|
|
74
82
|
return;
|
|
75
83
|
}
|
|
84
|
+
const bubbleMenuElement = menuEl.current;
|
|
85
|
+
bubbleMenuElement.style.visibility = "hidden";
|
|
86
|
+
bubbleMenuElement.style.position = "absolute";
|
|
76
87
|
const plugin = (0, import_extension_bubble_menu.BubbleMenuPlugin)({
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
element: bubbleMenuElement,
|
|
81
|
-
appendTo,
|
|
82
|
-
pluginKey,
|
|
83
|
-
shouldShow,
|
|
84
|
-
getReferencedVirtualElement,
|
|
85
|
-
options
|
|
88
|
+
...bubbleMenuPluginPropsRef.current,
|
|
89
|
+
editor: pluginEditor,
|
|
90
|
+
element: bubbleMenuElement
|
|
86
91
|
});
|
|
87
|
-
|
|
92
|
+
pluginEditor.registerPlugin(plugin);
|
|
93
|
+
const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey;
|
|
88
94
|
return () => {
|
|
89
|
-
|
|
95
|
+
pluginEditor.unregisterPlugin(createdPluginKey);
|
|
90
96
|
window.requestAnimationFrame(() => {
|
|
91
97
|
if (bubbleMenuElement.parentNode) {
|
|
92
98
|
bubbleMenuElement.parentNode.removeChild(bubbleMenuElement);
|
|
93
99
|
}
|
|
94
100
|
});
|
|
95
101
|
};
|
|
96
|
-
}, [
|
|
97
|
-
editor,
|
|
98
|
-
currentEditor,
|
|
99
|
-
pluginKey,
|
|
100
|
-
updateDelay,
|
|
101
|
-
resizeDelay,
|
|
102
|
-
appendTo,
|
|
103
|
-
shouldShow,
|
|
104
|
-
getReferencedVirtualElement,
|
|
105
|
-
options
|
|
106
|
-
]);
|
|
102
|
+
}, [pluginEditor]);
|
|
107
103
|
return (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...restProps, children }), menuEl.current);
|
|
108
104
|
}
|
|
109
105
|
);
|
package/dist/menus/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/menus/index.ts","../../src/menus/BubbleMenu.tsx","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["export * from './BubbleMenu.js'\nexport * from './FloatingMenu.js'\n","import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey = 'bubbleMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/menus/index.ts","../../src/menus/BubbleMenu.tsx","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["export * from './BubbleMenu.js'\nexport * from './FloatingMenu.js'\n","import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey = 'bubbleMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the bubble menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const bubbleMenuPluginProps: Omit<BubbleMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n }\n /**\n * The props for the bubble menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps)\n bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.style.position = 'absolute'\n\n const plugin = BubbleMenuPlugin({\n ...bubbleMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: bubbleMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey\n\n return () => {\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element' | 'editor'> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n ({ pluginKey = 'floatingMenu', editor, appendTo, shouldShow = null, options, children, ...restProps }, ref) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n useEffect(() => {\n const floatingMenuElement = menuEl.current\n\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n if (editor?.isDestroyed || (currentEditor as any)?.isDestroyed) {\n return\n }\n\n const attachToEditor = editor || currentEditor\n\n if (!attachToEditor) {\n console.warn(\n 'FloatingMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\n return\n }\n\n const plugin = FloatingMenuPlugin({\n editor: attachToEditor,\n element: floatingMenuElement,\n pluginKey,\n appendTo,\n shouldShow,\n options,\n })\n\n attachToEditor.registerPlugin(plugin)\n\n return () => {\n attachToEditor.unregisterPlugin(pluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor, currentEditor, appendTo, pluginKey, shouldShow, options])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n"],"mappings":"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","names":["import_react","React","import_react","import_react_dom","import_jsx_runtime","React"]}
|
package/dist/menus/index.js
CHANGED
|
@@ -24,49 +24,45 @@ var BubbleMenu = React.forwardRef(
|
|
|
24
24
|
ref.current = menuEl.current;
|
|
25
25
|
}
|
|
26
26
|
const { editor: currentEditor } = useCurrentEditor();
|
|
27
|
+
const pluginEditor = editor || currentEditor;
|
|
28
|
+
const bubbleMenuPluginProps = {
|
|
29
|
+
updateDelay,
|
|
30
|
+
resizeDelay,
|
|
31
|
+
appendTo,
|
|
32
|
+
pluginKey,
|
|
33
|
+
shouldShow,
|
|
34
|
+
getReferencedVirtualElement,
|
|
35
|
+
options
|
|
36
|
+
};
|
|
37
|
+
const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps);
|
|
38
|
+
bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps;
|
|
27
39
|
useEffect(() => {
|
|
28
|
-
|
|
29
|
-
bubbleMenuElement.style.visibility = "hidden";
|
|
30
|
-
bubbleMenuElement.style.position = "absolute";
|
|
31
|
-
if ((editor == null ? void 0 : editor.isDestroyed) || (currentEditor == null ? void 0 : currentEditor.isDestroyed)) {
|
|
40
|
+
if (pluginEditor == null ? void 0 : pluginEditor.isDestroyed) {
|
|
32
41
|
return;
|
|
33
42
|
}
|
|
34
|
-
|
|
35
|
-
if (!attachToEditor) {
|
|
43
|
+
if (!pluginEditor) {
|
|
36
44
|
console.warn("BubbleMenu component is not rendered inside of an editor component or does not have editor prop.");
|
|
37
45
|
return;
|
|
38
46
|
}
|
|
47
|
+
const bubbleMenuElement = menuEl.current;
|
|
48
|
+
bubbleMenuElement.style.visibility = "hidden";
|
|
49
|
+
bubbleMenuElement.style.position = "absolute";
|
|
39
50
|
const plugin = BubbleMenuPlugin({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
element: bubbleMenuElement,
|
|
44
|
-
appendTo,
|
|
45
|
-
pluginKey,
|
|
46
|
-
shouldShow,
|
|
47
|
-
getReferencedVirtualElement,
|
|
48
|
-
options
|
|
51
|
+
...bubbleMenuPluginPropsRef.current,
|
|
52
|
+
editor: pluginEditor,
|
|
53
|
+
element: bubbleMenuElement
|
|
49
54
|
});
|
|
50
|
-
|
|
55
|
+
pluginEditor.registerPlugin(plugin);
|
|
56
|
+
const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey;
|
|
51
57
|
return () => {
|
|
52
|
-
|
|
58
|
+
pluginEditor.unregisterPlugin(createdPluginKey);
|
|
53
59
|
window.requestAnimationFrame(() => {
|
|
54
60
|
if (bubbleMenuElement.parentNode) {
|
|
55
61
|
bubbleMenuElement.parentNode.removeChild(bubbleMenuElement);
|
|
56
62
|
}
|
|
57
63
|
});
|
|
58
64
|
};
|
|
59
|
-
}, [
|
|
60
|
-
editor,
|
|
61
|
-
currentEditor,
|
|
62
|
-
pluginKey,
|
|
63
|
-
updateDelay,
|
|
64
|
-
resizeDelay,
|
|
65
|
-
appendTo,
|
|
66
|
-
shouldShow,
|
|
67
|
-
getReferencedVirtualElement,
|
|
68
|
-
options
|
|
69
|
-
]);
|
|
65
|
+
}, [pluginEditor]);
|
|
70
66
|
return createPortal(/* @__PURE__ */ jsx("div", { ...restProps, children }), menuEl.current);
|
|
71
67
|
}
|
|
72
68
|
);
|
package/dist/menus/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey = 'bubbleMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>, 'editor'> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey = 'bubbleMenu',\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n getReferencedVirtualElement,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n /**\n * The editor instance where the bubble menu plugin will be registered.\n */\n const pluginEditor = editor || currentEditor\n\n // Creating a useMemo would be more computationally expensive than just\n // re-creating this object on every render.\n const bubbleMenuPluginProps: Omit<BubbleMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n }\n /**\n * The props for the bubble menu plugin. They are accessed inside a ref to\n * avoid running the useEffect hook and re-registering the plugin when the\n * props change.\n */\n const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps)\n bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.style.position = 'absolute'\n\n const plugin = BubbleMenuPlugin({\n ...bubbleMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: bubbleMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey\n\n return () => {\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef } from 'react'\nimport { createPortal } from 'react-dom'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<Optional<FloatingMenuPluginProps, 'pluginKey'>, 'element' | 'editor'> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n ({ pluginKey = 'floatingMenu', editor, appendTo, shouldShow = null, options, children, ...restProps }, ref) => {\n const menuEl = useRef(document.createElement('div'))\n\n if (typeof ref === 'function') {\n ref(menuEl.current)\n } else if (ref) {\n ref.current = menuEl.current\n }\n\n const { editor: currentEditor } = useCurrentEditor()\n\n useEffect(() => {\n const floatingMenuElement = menuEl.current\n\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n if (editor?.isDestroyed || (currentEditor as any)?.isDestroyed) {\n return\n }\n\n const attachToEditor = editor || currentEditor\n\n if (!attachToEditor) {\n console.warn(\n 'FloatingMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\n return\n }\n\n const plugin = FloatingMenuPlugin({\n editor: attachToEditor,\n element: floatingMenuElement,\n pluginKey,\n appendTo,\n shouldShow,\n options,\n })\n\n attachToEditor.registerPlugin(plugin)\n\n return () => {\n attachToEditor.unregisterPlugin(pluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editor, currentEditor, appendTo, pluginKey, shouldShow, options])\n\n return createPortal(<div {...restProps}>{children}</div>, menuEl.current)\n },\n)\n"],"mappings":"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","names":["useCurrentEditor","React","useEffect","useRef","createPortal","jsx"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/react",
|
|
3
3
|
"description": "React components for tiptap",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.9.0",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -48,20 +48,20 @@
|
|
|
48
48
|
"@types/react-dom": "^19.0.0",
|
|
49
49
|
"react": "^19.0.0",
|
|
50
50
|
"react-dom": "^19.0.0",
|
|
51
|
-
"@tiptap/core": "^3.
|
|
52
|
-
"@tiptap/pm": "^3.
|
|
51
|
+
"@tiptap/core": "^3.9.0",
|
|
52
|
+
"@tiptap/pm": "^3.9.0"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@tiptap/extension-bubble-menu": "^3.
|
|
56
|
-
"@tiptap/extension-floating-menu": "^3.
|
|
55
|
+
"@tiptap/extension-bubble-menu": "^3.9.0",
|
|
56
|
+
"@tiptap/extension-floating-menu": "^3.9.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
60
60
|
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
61
61
|
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
62
62
|
"@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
63
|
-
"@tiptap/core": "^3.
|
|
64
|
-
"@tiptap/pm": "^3.
|
|
63
|
+
"@tiptap/core": "^3.9.0",
|
|
64
|
+
"@tiptap/pm": "^3.9.0"
|
|
65
65
|
},
|
|
66
66
|
"repository": {
|
|
67
67
|
"type": "git",
|
package/src/menus/BubbleMenu.tsx
CHANGED
|
@@ -34,55 +34,63 @@ export const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(
|
|
|
34
34
|
|
|
35
35
|
const { editor: currentEditor } = useCurrentEditor()
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The editor instance where the bubble menu plugin will be registered.
|
|
39
|
+
*/
|
|
40
|
+
const pluginEditor = editor || currentEditor
|
|
41
|
+
|
|
42
|
+
// Creating a useMemo would be more computationally expensive than just
|
|
43
|
+
// re-creating this object on every render.
|
|
44
|
+
const bubbleMenuPluginProps: Omit<BubbleMenuPluginProps, 'editor' | 'element'> = {
|
|
45
|
+
updateDelay,
|
|
46
|
+
resizeDelay,
|
|
47
|
+
appendTo,
|
|
48
|
+
pluginKey,
|
|
49
|
+
shouldShow,
|
|
50
|
+
getReferencedVirtualElement,
|
|
51
|
+
options,
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The props for the bubble menu plugin. They are accessed inside a ref to
|
|
55
|
+
* avoid running the useEffect hook and re-registering the plugin when the
|
|
56
|
+
* props change.
|
|
57
|
+
*/
|
|
58
|
+
const bubbleMenuPluginPropsRef = useRef(bubbleMenuPluginProps)
|
|
59
|
+
bubbleMenuPluginPropsRef.current = bubbleMenuPluginProps
|
|
41
60
|
|
|
42
|
-
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (pluginEditor?.isDestroyed) {
|
|
43
63
|
return
|
|
44
64
|
}
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!attachToEditor) {
|
|
66
|
+
if (!pluginEditor) {
|
|
49
67
|
console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')
|
|
50
68
|
return
|
|
51
69
|
}
|
|
52
70
|
|
|
71
|
+
const bubbleMenuElement = menuEl.current
|
|
72
|
+
bubbleMenuElement.style.visibility = 'hidden'
|
|
73
|
+
bubbleMenuElement.style.position = 'absolute'
|
|
74
|
+
|
|
53
75
|
const plugin = BubbleMenuPlugin({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
editor: attachToEditor,
|
|
76
|
+
...bubbleMenuPluginPropsRef.current,
|
|
77
|
+
editor: pluginEditor,
|
|
57
78
|
element: bubbleMenuElement,
|
|
58
|
-
appendTo,
|
|
59
|
-
pluginKey,
|
|
60
|
-
shouldShow,
|
|
61
|
-
getReferencedVirtualElement,
|
|
62
|
-
options,
|
|
63
79
|
})
|
|
64
80
|
|
|
65
|
-
|
|
81
|
+
pluginEditor.registerPlugin(plugin)
|
|
82
|
+
|
|
83
|
+
const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey
|
|
66
84
|
|
|
67
85
|
return () => {
|
|
68
|
-
|
|
86
|
+
pluginEditor.unregisterPlugin(createdPluginKey)
|
|
69
87
|
window.requestAnimationFrame(() => {
|
|
70
88
|
if (bubbleMenuElement.parentNode) {
|
|
71
89
|
bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)
|
|
72
90
|
}
|
|
73
91
|
})
|
|
74
92
|
}
|
|
75
|
-
}, [
|
|
76
|
-
editor,
|
|
77
|
-
currentEditor,
|
|
78
|
-
pluginKey,
|
|
79
|
-
updateDelay,
|
|
80
|
-
resizeDelay,
|
|
81
|
-
appendTo,
|
|
82
|
-
shouldShow,
|
|
83
|
-
getReferencedVirtualElement,
|
|
84
|
-
options,
|
|
85
|
-
])
|
|
93
|
+
}, [pluginEditor])
|
|
86
94
|
|
|
87
95
|
return createPortal(<div {...restProps}>{children}</div>, menuEl.current)
|
|
88
96
|
},
|