@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.
@@ -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
- const bubbleMenuElement = menuEl.current;
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
- const attachToEditor = editor || currentEditor;
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
- updateDelay,
78
- resizeDelay,
79
- editor: attachToEditor,
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
- attachToEditor.registerPlugin(plugin);
92
+ pluginEditor.registerPlugin(plugin);
93
+ const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey;
88
94
  return () => {
89
- attachToEditor.unregisterPlugin(pluginKey);
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
  );
@@ -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 useEffect(() => {\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.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('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const plugin = BubbleMenuPlugin({\n updateDelay,\n resizeDelay,\n editor: attachToEditor,\n element: bubbleMenuElement,\n appendTo,\n pluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n })\n\n attachToEditor.registerPlugin(plugin)\n\n return () => {\n attachToEditor.unregisterPlugin(pluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [\n editor,\n currentEditor,\n pluginKey,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow,\n getReferencedVirtualElement,\n options,\n ])\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"]}
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"]}
@@ -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
- const bubbleMenuElement = menuEl.current;
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
- const attachToEditor = editor || currentEditor;
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
- updateDelay,
41
- resizeDelay,
42
- editor: attachToEditor,
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
- attachToEditor.registerPlugin(plugin);
55
+ pluginEditor.registerPlugin(plugin);
56
+ const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey;
51
57
  return () => {
52
- attachToEditor.unregisterPlugin(pluginKey);
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
  );
@@ -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 useEffect(() => {\n const bubbleMenuElement = menuEl.current\n bubbleMenuElement.style.visibility = 'hidden'\n bubbleMenuElement.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('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.')\n return\n }\n\n const plugin = BubbleMenuPlugin({\n updateDelay,\n resizeDelay,\n editor: attachToEditor,\n element: bubbleMenuElement,\n appendTo,\n pluginKey,\n shouldShow,\n getReferencedVirtualElement,\n options,\n })\n\n attachToEditor.registerPlugin(plugin)\n\n return () => {\n attachToEditor.unregisterPlugin(pluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [\n editor,\n currentEditor,\n pluginKey,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow,\n getReferencedVirtualElement,\n options,\n ])\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"]}
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.7.2",
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.7.2",
52
- "@tiptap/pm": "^3.7.2"
51
+ "@tiptap/core": "^3.9.0",
52
+ "@tiptap/pm": "^3.9.0"
53
53
  },
54
54
  "optionalDependencies": {
55
- "@tiptap/extension-bubble-menu": "^3.7.2",
56
- "@tiptap/extension-floating-menu": "^3.7.2"
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.7.2",
64
- "@tiptap/pm": "^3.7.2"
63
+ "@tiptap/core": "^3.9.0",
64
+ "@tiptap/pm": "^3.9.0"
65
65
  },
66
66
  "repository": {
67
67
  "type": "git",
@@ -34,55 +34,63 @@ export const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(
34
34
 
35
35
  const { editor: currentEditor } = useCurrentEditor()
36
36
 
37
- useEffect(() => {
38
- const bubbleMenuElement = menuEl.current
39
- bubbleMenuElement.style.visibility = 'hidden'
40
- bubbleMenuElement.style.position = 'absolute'
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
- if (editor?.isDestroyed || (currentEditor as any)?.isDestroyed) {
61
+ useEffect(() => {
62
+ if (pluginEditor?.isDestroyed) {
43
63
  return
44
64
  }
45
65
 
46
- const attachToEditor = editor || currentEditor
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
- updateDelay,
55
- resizeDelay,
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
- attachToEditor.registerPlugin(plugin)
81
+ pluginEditor.registerPlugin(plugin)
82
+
83
+ const createdPluginKey = bubbleMenuPluginPropsRef.current.pluginKey
66
84
 
67
85
  return () => {
68
- attachToEditor.unregisterPlugin(pluginKey)
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
  },