@tiptap/react
Advanced tools
| /** | ||
| * @vitest-environment node | ||
| */ | ||
| import { readFileSync } from 'node:fs' | ||
| import { fileURLToPath } from 'node:url' | ||
| import { describe, expect, it } from 'vitest' | ||
| // The package boundary must stay a client module so it can be imported from | ||
| // React Server Components without evaluating the class components inside. | ||
| const entries = ['./index.ts', './menus/index.ts'] | ||
| describe('use client boundary', () => { | ||
| it.each(entries)('%s starts with the "use client" directive', entry => { | ||
| const path = fileURLToPath(new URL(entry, import.meta.url)) | ||
| // The directive must be the very first statement (only a BOM may precede | ||
| // it), otherwise some RSC tooling ignores it. Do not trim leading blanks. | ||
| const firstLine = readFileSync(path, 'utf8') | ||
| .replace(/^\uFEFF/, '') | ||
| .split('\n')[0] | ||
| .trimEnd() | ||
| expect(firstLine).toMatch(/^(['"])use client\1;?$/) | ||
| }) | ||
| }) |
+1
-0
| "use strict"; | ||
| "use client"; | ||
| var __create = Object.create; | ||
@@ -3,0 +4,0 @@ var __defProp = Object.defineProperty; |
+2
-0
@@ -0,1 +1,3 @@ | ||
| "use client"; | ||
| // src/Context.tsx | ||
@@ -2,0 +4,0 @@ import { createContext, useContext, useMemo } from "react"; |
| "use strict"; | ||
| "use client"; | ||
| var __create = Object.create; | ||
@@ -3,0 +4,0 @@ var __defProp = Object.defineProperty; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/menus/index.ts","../../src/menus/BubbleMenu.tsx","../../src/menus/getAutoPluginKey.ts","../../src/menus/useMenuElementProps.ts","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["export * from './BubbleMenu.js'\nexport * from './FloatingMenu.js'\n","import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<\n Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>,\n 'editor'\n> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey,\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 const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'bubbleMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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: resolvedPluginKey,\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 /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'BubbleMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\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 skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n","import { PluginKey } from '@tiptap/pm/state'\n\nexport function getAutoPluginKey(pluginKey: PluginKey | string | undefined, defaultName: string) {\n return pluginKey ?? new PluginKey(defaultName)\n}\n","import type { CSSProperties, HTMLAttributes } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ntype MenuElementProps = HTMLAttributes<HTMLDivElement>\ntype MenuSyntheticEvent = Event & {\n nativeEvent: Event\n currentTarget: HTMLDivElement\n target: EventTarget | null\n persist: () => void\n isDefaultPrevented: () => boolean\n isPropagationStopped: () => boolean\n}\ntype MenuEventListener = (event: MenuSyntheticEvent) => void\ntype MenuNativeListener = (event: Event) => void\ntype MenuEventListenerOptions = {\n capture?: boolean\n}\n\ntype EventListenerEntry = {\n eventName: string\n listener: MenuNativeListener\n options?: MenuEventListenerOptions\n}\n\nconst PLUGIN_MANAGED_STYLE_PROPERTIES = new Set([\n 'left',\n 'opacity',\n 'position',\n 'top',\n 'visibility',\n 'width',\n])\nconst UNITLESS_STYLE_PROPERTIES = new Set([\n 'animationIterationCount',\n 'aspectRatio',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'fillOpacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'scale',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n])\nconst ATTRIBUTE_EXCLUSIONS = new Set(['children', 'className', 'style'])\nconst DIRECT_PROPERTY_KEYS = new Set(['tabIndex'])\nconst FORWARDED_ATTRIBUTE_KEYS = new Set([\n 'accessKey',\n 'autoCapitalize',\n 'contentEditable',\n 'contextMenu',\n 'dir',\n 'draggable',\n 'enterKeyHint',\n 'hidden',\n 'id',\n 'lang',\n 'nonce',\n 'role',\n 'slot',\n 'spellCheck',\n 'tabIndex',\n 'title',\n 'translate',\n])\nconst SPECIAL_EVENT_NAMES: Record<string, string> = {\n Blur: 'focusout',\n DoubleClick: 'dblclick',\n Focus: 'focusin',\n MouseEnter: 'mouseenter',\n MouseLeave: 'mouseleave',\n}\n\nfunction isEventProp(key: string, value: unknown): value is MenuEventListener {\n return /^on[A-Z]/.test(key) && typeof value === 'function'\n}\n\nfunction toAttributeName(key: string) {\n if (key.startsWith('aria-') || key.startsWith('data-')) {\n return key\n }\n\n return key\n}\n\nfunction isForwardedAttributeKey(key: string) {\n return key.startsWith('aria-') || key.startsWith('data-') || FORWARDED_ATTRIBUTE_KEYS.has(key)\n}\n\nfunction toStylePropertyName(key: string) {\n if (key.startsWith('--')) {\n return key\n }\n\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\n}\n\nfunction toEventConfig(key: string) {\n const useCapture = key.endsWith('Capture')\n const baseKey = useCapture ? key.slice(0, -7) : key\n const reactEventName = baseKey.slice(2)\n const eventName = SPECIAL_EVENT_NAMES[reactEventName] ?? reactEventName.toLowerCase()\n\n return {\n eventName,\n options: useCapture ? { capture: true } : undefined,\n }\n}\n\nfunction createSyntheticEvent(element: HTMLDivElement, nativeEvent: Event): MenuSyntheticEvent {\n let defaultPrevented = nativeEvent.defaultPrevented\n let propagationStopped = false\n const syntheticEvent = Object.create(nativeEvent)\n\n Object.defineProperties(syntheticEvent, {\n nativeEvent: { value: nativeEvent },\n currentTarget: { value: element },\n target: { value: nativeEvent.target },\n persist: { value: () => undefined },\n isDefaultPrevented: { value: () => defaultPrevented },\n isPropagationStopped: { value: () => propagationStopped },\n preventDefault: {\n value: () => {\n defaultPrevented = true\n nativeEvent.preventDefault()\n },\n },\n stopPropagation: {\n value: () => {\n propagationStopped = true\n nativeEvent.stopPropagation()\n },\n },\n })\n\n return syntheticEvent as MenuSyntheticEvent\n}\n\nfunction isDirectPropertyKey(key: string) {\n return DIRECT_PROPERTY_KEYS.has(key)\n}\n\nfunction setDirectProperty(element: HTMLDivElement, key: string, value: unknown) {\n if (key === 'tabIndex') {\n element.tabIndex = Number(value)\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = value\n}\n\nfunction clearDirectProperty(element: HTMLDivElement, key: string) {\n if (key === 'tabIndex') {\n element.removeAttribute('tabindex')\n return\n }\n\n const propertyValue = (element as unknown as Record<string, unknown>)[key]\n\n if (typeof propertyValue === 'boolean') {\n ;(element as unknown as Record<string, unknown>)[key] = false\n return\n }\n\n if (typeof propertyValue === 'number') {\n ;(element as unknown as Record<string, unknown>)[key] = 0\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = ''\n}\n\nfunction toStyleValue(styleName: string, value: string | number) {\n if (\n typeof value !== 'number' ||\n value === 0 ||\n styleName.startsWith('--') ||\n UNITLESS_STYLE_PROPERTIES.has(styleName)\n ) {\n return String(value)\n }\n\n return `${value}px`\n}\n\nfunction removeStyleProperty(element: HTMLDivElement, styleName: string) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.removeProperty(toStylePropertyName(styleName))\n}\n\nfunction applyStyleProperty(element: HTMLDivElement, styleName: string, value: string | number) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value))\n}\n\nfunction syncAttributes(\n element: HTMLDivElement,\n prevProps: MenuElementProps,\n nextProps: MenuElementProps,\n) {\n const allKeys = new Set([...Object.keys(prevProps), ...Object.keys(nextProps)])\n\n allKeys.forEach(key => {\n if (\n ATTRIBUTE_EXCLUSIONS.has(key) ||\n !isForwardedAttributeKey(key) ||\n isEventProp(key, prevProps[key as keyof MenuElementProps]) ||\n isEventProp(key, nextProps[key as keyof MenuElementProps])\n ) {\n return\n }\n\n const prevValue = prevProps[key as keyof MenuElementProps]\n const nextValue = nextProps[key as keyof MenuElementProps]\n\n if (prevValue === nextValue) {\n return\n }\n\n const attributeName = toAttributeName(key)\n\n if (nextValue == null || nextValue === false) {\n if (isDirectPropertyKey(key)) {\n clearDirectProperty(element, key)\n }\n\n element.removeAttribute(attributeName)\n return\n }\n\n if (nextValue === true) {\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, true)\n }\n\n element.setAttribute(attributeName, '')\n return\n }\n\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, nextValue)\n return\n }\n\n element.setAttribute(attributeName, String(nextValue))\n })\n}\n\nfunction syncClassName(element: HTMLDivElement, prevClassName?: string, nextClassName?: string) {\n if (prevClassName === nextClassName) {\n return\n }\n\n if (nextClassName) {\n element.className = nextClassName\n return\n }\n\n element.removeAttribute('class')\n}\n\nfunction syncStyles(\n element: HTMLDivElement,\n prevStyle: CSSProperties | undefined,\n nextStyle: CSSProperties | undefined,\n) {\n const previousStyle = prevStyle ?? {}\n const currentStyle = nextStyle ?? {}\n const allStyleNames = new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)])\n\n allStyleNames.forEach(styleName => {\n const prevValue = previousStyle[styleName as keyof CSSProperties]\n const nextValue = currentStyle[styleName as keyof CSSProperties]\n\n if (prevValue === nextValue) {\n return\n }\n\n if (nextValue == null) {\n removeStyleProperty(element, styleName)\n return\n }\n\n applyStyleProperty(element, styleName, nextValue as string | number)\n })\n}\n\nfunction syncEventListeners(\n element: HTMLDivElement,\n prevListeners: EventListenerEntry[],\n nextProps: MenuElementProps,\n) {\n prevListeners.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n\n const nextListeners: EventListenerEntry[] = []\n\n Object.entries(nextProps).forEach(([key, value]) => {\n if (!isEventProp(key, value)) {\n return\n }\n\n const { eventName, options } = toEventConfig(key)\n const listener: MenuNativeListener = event => {\n value(createSyntheticEvent(element, event))\n }\n\n element.addEventListener(eventName, listener, options)\n nextListeners.push({ eventName, listener, options })\n })\n\n return nextListeners\n}\n\nexport function useMenuElementProps(element: HTMLDivElement, props: MenuElementProps) {\n const previousPropsRef = useRef<MenuElementProps>({})\n const listenersRef = useRef<EventListenerEntry[]>([])\n\n useIsomorphicLayoutEffect(() => {\n const previousProps = previousPropsRef.current\n\n syncClassName(element, previousProps.className, props.className)\n syncStyles(element, previousProps.style, props.style)\n syncAttributes(element, previousProps, props)\n listenersRef.current = syncEventListeners(element, listenersRef.current, props)\n previousPropsRef.current = props\n\n return () => {\n listenersRef.current.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n listenersRef.current = []\n }\n }, [element, props])\n}\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<\n Optional<FloatingMenuPluginProps, 'pluginKey'>,\n 'element' | 'editor'\n> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n {\n pluginKey,\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'floatingMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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 floating 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 floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating 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 floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\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 floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n"],"mappings":"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","names":["import_react","React","import_react","import_react_dom","React"]} | ||
| {"version":3,"sources":["../../src/menus/index.ts","../../src/menus/BubbleMenu.tsx","../../src/menus/getAutoPluginKey.ts","../../src/menus/useMenuElementProps.ts","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["'use client'\n\nexport * from './BubbleMenu.js'\nexport * from './FloatingMenu.js'\n","import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<\n Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>,\n 'editor'\n> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey,\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 const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'bubbleMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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: resolvedPluginKey,\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 /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'BubbleMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\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 skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n","import { PluginKey } from '@tiptap/pm/state'\n\nexport function getAutoPluginKey(pluginKey: PluginKey | string | undefined, defaultName: string) {\n return pluginKey ?? new PluginKey(defaultName)\n}\n","import type { CSSProperties, HTMLAttributes } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ntype MenuElementProps = HTMLAttributes<HTMLDivElement>\ntype MenuSyntheticEvent = Event & {\n nativeEvent: Event\n currentTarget: HTMLDivElement\n target: EventTarget | null\n persist: () => void\n isDefaultPrevented: () => boolean\n isPropagationStopped: () => boolean\n}\ntype MenuEventListener = (event: MenuSyntheticEvent) => void\ntype MenuNativeListener = (event: Event) => void\ntype MenuEventListenerOptions = {\n capture?: boolean\n}\n\ntype EventListenerEntry = {\n eventName: string\n listener: MenuNativeListener\n options?: MenuEventListenerOptions\n}\n\nconst PLUGIN_MANAGED_STYLE_PROPERTIES = new Set([\n 'left',\n 'opacity',\n 'position',\n 'top',\n 'visibility',\n 'width',\n])\nconst UNITLESS_STYLE_PROPERTIES = new Set([\n 'animationIterationCount',\n 'aspectRatio',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'fillOpacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'scale',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n])\nconst ATTRIBUTE_EXCLUSIONS = new Set(['children', 'className', 'style'])\nconst DIRECT_PROPERTY_KEYS = new Set(['tabIndex'])\nconst FORWARDED_ATTRIBUTE_KEYS = new Set([\n 'accessKey',\n 'autoCapitalize',\n 'contentEditable',\n 'contextMenu',\n 'dir',\n 'draggable',\n 'enterKeyHint',\n 'hidden',\n 'id',\n 'lang',\n 'nonce',\n 'role',\n 'slot',\n 'spellCheck',\n 'tabIndex',\n 'title',\n 'translate',\n])\nconst SPECIAL_EVENT_NAMES: Record<string, string> = {\n Blur: 'focusout',\n DoubleClick: 'dblclick',\n Focus: 'focusin',\n MouseEnter: 'mouseenter',\n MouseLeave: 'mouseleave',\n}\n\nfunction isEventProp(key: string, value: unknown): value is MenuEventListener {\n return /^on[A-Z]/.test(key) && typeof value === 'function'\n}\n\nfunction toAttributeName(key: string) {\n if (key.startsWith('aria-') || key.startsWith('data-')) {\n return key\n }\n\n return key\n}\n\nfunction isForwardedAttributeKey(key: string) {\n return key.startsWith('aria-') || key.startsWith('data-') || FORWARDED_ATTRIBUTE_KEYS.has(key)\n}\n\nfunction toStylePropertyName(key: string) {\n if (key.startsWith('--')) {\n return key\n }\n\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\n}\n\nfunction toEventConfig(key: string) {\n const useCapture = key.endsWith('Capture')\n const baseKey = useCapture ? key.slice(0, -7) : key\n const reactEventName = baseKey.slice(2)\n const eventName = SPECIAL_EVENT_NAMES[reactEventName] ?? reactEventName.toLowerCase()\n\n return {\n eventName,\n options: useCapture ? { capture: true } : undefined,\n }\n}\n\nfunction createSyntheticEvent(element: HTMLDivElement, nativeEvent: Event): MenuSyntheticEvent {\n let defaultPrevented = nativeEvent.defaultPrevented\n let propagationStopped = false\n const syntheticEvent = Object.create(nativeEvent)\n\n Object.defineProperties(syntheticEvent, {\n nativeEvent: { value: nativeEvent },\n currentTarget: { value: element },\n target: { value: nativeEvent.target },\n persist: { value: () => undefined },\n isDefaultPrevented: { value: () => defaultPrevented },\n isPropagationStopped: { value: () => propagationStopped },\n preventDefault: {\n value: () => {\n defaultPrevented = true\n nativeEvent.preventDefault()\n },\n },\n stopPropagation: {\n value: () => {\n propagationStopped = true\n nativeEvent.stopPropagation()\n },\n },\n })\n\n return syntheticEvent as MenuSyntheticEvent\n}\n\nfunction isDirectPropertyKey(key: string) {\n return DIRECT_PROPERTY_KEYS.has(key)\n}\n\nfunction setDirectProperty(element: HTMLDivElement, key: string, value: unknown) {\n if (key === 'tabIndex') {\n element.tabIndex = Number(value)\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = value\n}\n\nfunction clearDirectProperty(element: HTMLDivElement, key: string) {\n if (key === 'tabIndex') {\n element.removeAttribute('tabindex')\n return\n }\n\n const propertyValue = (element as unknown as Record<string, unknown>)[key]\n\n if (typeof propertyValue === 'boolean') {\n ;(element as unknown as Record<string, unknown>)[key] = false\n return\n }\n\n if (typeof propertyValue === 'number') {\n ;(element as unknown as Record<string, unknown>)[key] = 0\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = ''\n}\n\nfunction toStyleValue(styleName: string, value: string | number) {\n if (\n typeof value !== 'number' ||\n value === 0 ||\n styleName.startsWith('--') ||\n UNITLESS_STYLE_PROPERTIES.has(styleName)\n ) {\n return String(value)\n }\n\n return `${value}px`\n}\n\nfunction removeStyleProperty(element: HTMLDivElement, styleName: string) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.removeProperty(toStylePropertyName(styleName))\n}\n\nfunction applyStyleProperty(element: HTMLDivElement, styleName: string, value: string | number) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value))\n}\n\nfunction syncAttributes(\n element: HTMLDivElement,\n prevProps: MenuElementProps,\n nextProps: MenuElementProps,\n) {\n const allKeys = new Set([...Object.keys(prevProps), ...Object.keys(nextProps)])\n\n allKeys.forEach(key => {\n if (\n ATTRIBUTE_EXCLUSIONS.has(key) ||\n !isForwardedAttributeKey(key) ||\n isEventProp(key, prevProps[key as keyof MenuElementProps]) ||\n isEventProp(key, nextProps[key as keyof MenuElementProps])\n ) {\n return\n }\n\n const prevValue = prevProps[key as keyof MenuElementProps]\n const nextValue = nextProps[key as keyof MenuElementProps]\n\n if (prevValue === nextValue) {\n return\n }\n\n const attributeName = toAttributeName(key)\n\n if (nextValue == null || nextValue === false) {\n if (isDirectPropertyKey(key)) {\n clearDirectProperty(element, key)\n }\n\n element.removeAttribute(attributeName)\n return\n }\n\n if (nextValue === true) {\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, true)\n }\n\n element.setAttribute(attributeName, '')\n return\n }\n\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, nextValue)\n return\n }\n\n element.setAttribute(attributeName, String(nextValue))\n })\n}\n\nfunction syncClassName(element: HTMLDivElement, prevClassName?: string, nextClassName?: string) {\n if (prevClassName === nextClassName) {\n return\n }\n\n if (nextClassName) {\n element.className = nextClassName\n return\n }\n\n element.removeAttribute('class')\n}\n\nfunction syncStyles(\n element: HTMLDivElement,\n prevStyle: CSSProperties | undefined,\n nextStyle: CSSProperties | undefined,\n) {\n const previousStyle = prevStyle ?? {}\n const currentStyle = nextStyle ?? {}\n const allStyleNames = new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)])\n\n allStyleNames.forEach(styleName => {\n const prevValue = previousStyle[styleName as keyof CSSProperties]\n const nextValue = currentStyle[styleName as keyof CSSProperties]\n\n if (prevValue === nextValue) {\n return\n }\n\n if (nextValue == null) {\n removeStyleProperty(element, styleName)\n return\n }\n\n applyStyleProperty(element, styleName, nextValue as string | number)\n })\n}\n\nfunction syncEventListeners(\n element: HTMLDivElement,\n prevListeners: EventListenerEntry[],\n nextProps: MenuElementProps,\n) {\n prevListeners.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n\n const nextListeners: EventListenerEntry[] = []\n\n Object.entries(nextProps).forEach(([key, value]) => {\n if (!isEventProp(key, value)) {\n return\n }\n\n const { eventName, options } = toEventConfig(key)\n const listener: MenuNativeListener = event => {\n value(createSyntheticEvent(element, event))\n }\n\n element.addEventListener(eventName, listener, options)\n nextListeners.push({ eventName, listener, options })\n })\n\n return nextListeners\n}\n\nexport function useMenuElementProps(element: HTMLDivElement, props: MenuElementProps) {\n const previousPropsRef = useRef<MenuElementProps>({})\n const listenersRef = useRef<EventListenerEntry[]>([])\n\n useIsomorphicLayoutEffect(() => {\n const previousProps = previousPropsRef.current\n\n syncClassName(element, previousProps.className, props.className)\n syncStyles(element, previousProps.style, props.style)\n syncAttributes(element, previousProps, props)\n listenersRef.current = syncEventListeners(element, listenersRef.current, props)\n previousPropsRef.current = props\n\n return () => {\n listenersRef.current.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n listenersRef.current = []\n }\n }, [element, props])\n}\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<\n Optional<FloatingMenuPluginProps, 'pluginKey'>,\n 'element' | 'editor'\n> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n {\n pluginKey,\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'floatingMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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 floating 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 floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating 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 floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\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 floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n"],"mappings":"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","names":["import_react","React","import_react","import_react_dom","React"]} |
@@ -0,1 +1,3 @@ | ||
| "use client"; | ||
| // src/menus/BubbleMenu.tsx | ||
@@ -2,0 +4,0 @@ import { BubbleMenuPlugin } from "@tiptap/extension-bubble-menu"; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/getAutoPluginKey.ts","../../src/menus/useMenuElementProps.ts","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<\n Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>,\n 'editor'\n> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey,\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 const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'bubbleMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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: resolvedPluginKey,\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 /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'BubbleMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\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 skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n","import { PluginKey } from '@tiptap/pm/state'\n\nexport function getAutoPluginKey(pluginKey: PluginKey | string | undefined, defaultName: string) {\n return pluginKey ?? new PluginKey(defaultName)\n}\n","import type { CSSProperties, HTMLAttributes } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ntype MenuElementProps = HTMLAttributes<HTMLDivElement>\ntype MenuSyntheticEvent = Event & {\n nativeEvent: Event\n currentTarget: HTMLDivElement\n target: EventTarget | null\n persist: () => void\n isDefaultPrevented: () => boolean\n isPropagationStopped: () => boolean\n}\ntype MenuEventListener = (event: MenuSyntheticEvent) => void\ntype MenuNativeListener = (event: Event) => void\ntype MenuEventListenerOptions = {\n capture?: boolean\n}\n\ntype EventListenerEntry = {\n eventName: string\n listener: MenuNativeListener\n options?: MenuEventListenerOptions\n}\n\nconst PLUGIN_MANAGED_STYLE_PROPERTIES = new Set([\n 'left',\n 'opacity',\n 'position',\n 'top',\n 'visibility',\n 'width',\n])\nconst UNITLESS_STYLE_PROPERTIES = new Set([\n 'animationIterationCount',\n 'aspectRatio',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'fillOpacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'scale',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n])\nconst ATTRIBUTE_EXCLUSIONS = new Set(['children', 'className', 'style'])\nconst DIRECT_PROPERTY_KEYS = new Set(['tabIndex'])\nconst FORWARDED_ATTRIBUTE_KEYS = new Set([\n 'accessKey',\n 'autoCapitalize',\n 'contentEditable',\n 'contextMenu',\n 'dir',\n 'draggable',\n 'enterKeyHint',\n 'hidden',\n 'id',\n 'lang',\n 'nonce',\n 'role',\n 'slot',\n 'spellCheck',\n 'tabIndex',\n 'title',\n 'translate',\n])\nconst SPECIAL_EVENT_NAMES: Record<string, string> = {\n Blur: 'focusout',\n DoubleClick: 'dblclick',\n Focus: 'focusin',\n MouseEnter: 'mouseenter',\n MouseLeave: 'mouseleave',\n}\n\nfunction isEventProp(key: string, value: unknown): value is MenuEventListener {\n return /^on[A-Z]/.test(key) && typeof value === 'function'\n}\n\nfunction toAttributeName(key: string) {\n if (key.startsWith('aria-') || key.startsWith('data-')) {\n return key\n }\n\n return key\n}\n\nfunction isForwardedAttributeKey(key: string) {\n return key.startsWith('aria-') || key.startsWith('data-') || FORWARDED_ATTRIBUTE_KEYS.has(key)\n}\n\nfunction toStylePropertyName(key: string) {\n if (key.startsWith('--')) {\n return key\n }\n\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\n}\n\nfunction toEventConfig(key: string) {\n const useCapture = key.endsWith('Capture')\n const baseKey = useCapture ? key.slice(0, -7) : key\n const reactEventName = baseKey.slice(2)\n const eventName = SPECIAL_EVENT_NAMES[reactEventName] ?? reactEventName.toLowerCase()\n\n return {\n eventName,\n options: useCapture ? { capture: true } : undefined,\n }\n}\n\nfunction createSyntheticEvent(element: HTMLDivElement, nativeEvent: Event): MenuSyntheticEvent {\n let defaultPrevented = nativeEvent.defaultPrevented\n let propagationStopped = false\n const syntheticEvent = Object.create(nativeEvent)\n\n Object.defineProperties(syntheticEvent, {\n nativeEvent: { value: nativeEvent },\n currentTarget: { value: element },\n target: { value: nativeEvent.target },\n persist: { value: () => undefined },\n isDefaultPrevented: { value: () => defaultPrevented },\n isPropagationStopped: { value: () => propagationStopped },\n preventDefault: {\n value: () => {\n defaultPrevented = true\n nativeEvent.preventDefault()\n },\n },\n stopPropagation: {\n value: () => {\n propagationStopped = true\n nativeEvent.stopPropagation()\n },\n },\n })\n\n return syntheticEvent as MenuSyntheticEvent\n}\n\nfunction isDirectPropertyKey(key: string) {\n return DIRECT_PROPERTY_KEYS.has(key)\n}\n\nfunction setDirectProperty(element: HTMLDivElement, key: string, value: unknown) {\n if (key === 'tabIndex') {\n element.tabIndex = Number(value)\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = value\n}\n\nfunction clearDirectProperty(element: HTMLDivElement, key: string) {\n if (key === 'tabIndex') {\n element.removeAttribute('tabindex')\n return\n }\n\n const propertyValue = (element as unknown as Record<string, unknown>)[key]\n\n if (typeof propertyValue === 'boolean') {\n ;(element as unknown as Record<string, unknown>)[key] = false\n return\n }\n\n if (typeof propertyValue === 'number') {\n ;(element as unknown as Record<string, unknown>)[key] = 0\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = ''\n}\n\nfunction toStyleValue(styleName: string, value: string | number) {\n if (\n typeof value !== 'number' ||\n value === 0 ||\n styleName.startsWith('--') ||\n UNITLESS_STYLE_PROPERTIES.has(styleName)\n ) {\n return String(value)\n }\n\n return `${value}px`\n}\n\nfunction removeStyleProperty(element: HTMLDivElement, styleName: string) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.removeProperty(toStylePropertyName(styleName))\n}\n\nfunction applyStyleProperty(element: HTMLDivElement, styleName: string, value: string | number) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value))\n}\n\nfunction syncAttributes(\n element: HTMLDivElement,\n prevProps: MenuElementProps,\n nextProps: MenuElementProps,\n) {\n const allKeys = new Set([...Object.keys(prevProps), ...Object.keys(nextProps)])\n\n allKeys.forEach(key => {\n if (\n ATTRIBUTE_EXCLUSIONS.has(key) ||\n !isForwardedAttributeKey(key) ||\n isEventProp(key, prevProps[key as keyof MenuElementProps]) ||\n isEventProp(key, nextProps[key as keyof MenuElementProps])\n ) {\n return\n }\n\n const prevValue = prevProps[key as keyof MenuElementProps]\n const nextValue = nextProps[key as keyof MenuElementProps]\n\n if (prevValue === nextValue) {\n return\n }\n\n const attributeName = toAttributeName(key)\n\n if (nextValue == null || nextValue === false) {\n if (isDirectPropertyKey(key)) {\n clearDirectProperty(element, key)\n }\n\n element.removeAttribute(attributeName)\n return\n }\n\n if (nextValue === true) {\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, true)\n }\n\n element.setAttribute(attributeName, '')\n return\n }\n\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, nextValue)\n return\n }\n\n element.setAttribute(attributeName, String(nextValue))\n })\n}\n\nfunction syncClassName(element: HTMLDivElement, prevClassName?: string, nextClassName?: string) {\n if (prevClassName === nextClassName) {\n return\n }\n\n if (nextClassName) {\n element.className = nextClassName\n return\n }\n\n element.removeAttribute('class')\n}\n\nfunction syncStyles(\n element: HTMLDivElement,\n prevStyle: CSSProperties | undefined,\n nextStyle: CSSProperties | undefined,\n) {\n const previousStyle = prevStyle ?? {}\n const currentStyle = nextStyle ?? {}\n const allStyleNames = new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)])\n\n allStyleNames.forEach(styleName => {\n const prevValue = previousStyle[styleName as keyof CSSProperties]\n const nextValue = currentStyle[styleName as keyof CSSProperties]\n\n if (prevValue === nextValue) {\n return\n }\n\n if (nextValue == null) {\n removeStyleProperty(element, styleName)\n return\n }\n\n applyStyleProperty(element, styleName, nextValue as string | number)\n })\n}\n\nfunction syncEventListeners(\n element: HTMLDivElement,\n prevListeners: EventListenerEntry[],\n nextProps: MenuElementProps,\n) {\n prevListeners.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n\n const nextListeners: EventListenerEntry[] = []\n\n Object.entries(nextProps).forEach(([key, value]) => {\n if (!isEventProp(key, value)) {\n return\n }\n\n const { eventName, options } = toEventConfig(key)\n const listener: MenuNativeListener = event => {\n value(createSyntheticEvent(element, event))\n }\n\n element.addEventListener(eventName, listener, options)\n nextListeners.push({ eventName, listener, options })\n })\n\n return nextListeners\n}\n\nexport function useMenuElementProps(element: HTMLDivElement, props: MenuElementProps) {\n const previousPropsRef = useRef<MenuElementProps>({})\n const listenersRef = useRef<EventListenerEntry[]>([])\n\n useIsomorphicLayoutEffect(() => {\n const previousProps = previousPropsRef.current\n\n syncClassName(element, previousProps.className, props.className)\n syncStyles(element, previousProps.style, props.style)\n syncAttributes(element, previousProps, props)\n listenersRef.current = syncEventListeners(element, listenersRef.current, props)\n previousPropsRef.current = props\n\n return () => {\n listenersRef.current.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n listenersRef.current = []\n }\n }, [element, props])\n}\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<\n Optional<FloatingMenuPluginProps, 'pluginKey'>,\n 'element' | 'editor'\n> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n {\n pluginKey,\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'floatingMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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 floating 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 floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating 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 floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\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 floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","useCurrentEditor","React","useEffect","useRef","useState","createPortal","React","useRef","useCurrentEditor","useState","useEffect","createPortal"]} | ||
| {"version":3,"sources":["../../src/menus/BubbleMenu.tsx","../../src/menus/getAutoPluginKey.ts","../../src/menus/useMenuElementProps.ts","../../src/menus/FloatingMenu.tsx"],"sourcesContent":["import { type BubbleMenuPluginProps, BubbleMenuPlugin } from '@tiptap/extension-bubble-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type BubbleMenuProps = Optional<\n Omit<Optional<BubbleMenuPluginProps, 'pluginKey'>, 'element'>,\n 'editor'\n> &\n React.HTMLAttributes<HTMLDivElement>\n\nexport const BubbleMenu = React.forwardRef<HTMLDivElement, BubbleMenuProps>(\n (\n {\n pluginKey,\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 const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'bubbleMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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: resolvedPluginKey,\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 /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\n console.warn(\n 'BubbleMenu component is not rendered inside of an editor component or does not have editor prop.',\n )\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 skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (bubbleMenuElement.parentNode) {\n bubbleMenuElement.parentNode.removeChild(bubbleMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: bubbleMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n getReferencedVirtualElement,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n","import { PluginKey } from '@tiptap/pm/state'\n\nexport function getAutoPluginKey(pluginKey: PluginKey | string | undefined, defaultName: string) {\n return pluginKey ?? new PluginKey(defaultName)\n}\n","import type { CSSProperties, HTMLAttributes } from 'react'\nimport { useEffect, useLayoutEffect, useRef } from 'react'\n\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect\n\ntype MenuElementProps = HTMLAttributes<HTMLDivElement>\ntype MenuSyntheticEvent = Event & {\n nativeEvent: Event\n currentTarget: HTMLDivElement\n target: EventTarget | null\n persist: () => void\n isDefaultPrevented: () => boolean\n isPropagationStopped: () => boolean\n}\ntype MenuEventListener = (event: MenuSyntheticEvent) => void\ntype MenuNativeListener = (event: Event) => void\ntype MenuEventListenerOptions = {\n capture?: boolean\n}\n\ntype EventListenerEntry = {\n eventName: string\n listener: MenuNativeListener\n options?: MenuEventListenerOptions\n}\n\nconst PLUGIN_MANAGED_STYLE_PROPERTIES = new Set([\n 'left',\n 'opacity',\n 'position',\n 'top',\n 'visibility',\n 'width',\n])\nconst UNITLESS_STYLE_PROPERTIES = new Set([\n 'animationIterationCount',\n 'aspectRatio',\n 'borderImageOutset',\n 'borderImageSlice',\n 'borderImageWidth',\n 'columnCount',\n 'columns',\n 'fillOpacity',\n 'flex',\n 'flexGrow',\n 'flexShrink',\n 'fontWeight',\n 'gridArea',\n 'gridColumn',\n 'gridColumnEnd',\n 'gridColumnStart',\n 'gridRow',\n 'gridRowEnd',\n 'gridRowStart',\n 'lineClamp',\n 'lineHeight',\n 'opacity',\n 'order',\n 'orphans',\n 'scale',\n 'stopOpacity',\n 'strokeDasharray',\n 'strokeDashoffset',\n 'strokeMiterlimit',\n 'strokeOpacity',\n 'strokeWidth',\n 'tabSize',\n 'widows',\n 'zIndex',\n 'zoom',\n])\nconst ATTRIBUTE_EXCLUSIONS = new Set(['children', 'className', 'style'])\nconst DIRECT_PROPERTY_KEYS = new Set(['tabIndex'])\nconst FORWARDED_ATTRIBUTE_KEYS = new Set([\n 'accessKey',\n 'autoCapitalize',\n 'contentEditable',\n 'contextMenu',\n 'dir',\n 'draggable',\n 'enterKeyHint',\n 'hidden',\n 'id',\n 'lang',\n 'nonce',\n 'role',\n 'slot',\n 'spellCheck',\n 'tabIndex',\n 'title',\n 'translate',\n])\nconst SPECIAL_EVENT_NAMES: Record<string, string> = {\n Blur: 'focusout',\n DoubleClick: 'dblclick',\n Focus: 'focusin',\n MouseEnter: 'mouseenter',\n MouseLeave: 'mouseleave',\n}\n\nfunction isEventProp(key: string, value: unknown): value is MenuEventListener {\n return /^on[A-Z]/.test(key) && typeof value === 'function'\n}\n\nfunction toAttributeName(key: string) {\n if (key.startsWith('aria-') || key.startsWith('data-')) {\n return key\n }\n\n return key\n}\n\nfunction isForwardedAttributeKey(key: string) {\n return key.startsWith('aria-') || key.startsWith('data-') || FORWARDED_ATTRIBUTE_KEYS.has(key)\n}\n\nfunction toStylePropertyName(key: string) {\n if (key.startsWith('--')) {\n return key\n }\n\n return key.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)\n}\n\nfunction toEventConfig(key: string) {\n const useCapture = key.endsWith('Capture')\n const baseKey = useCapture ? key.slice(0, -7) : key\n const reactEventName = baseKey.slice(2)\n const eventName = SPECIAL_EVENT_NAMES[reactEventName] ?? reactEventName.toLowerCase()\n\n return {\n eventName,\n options: useCapture ? { capture: true } : undefined,\n }\n}\n\nfunction createSyntheticEvent(element: HTMLDivElement, nativeEvent: Event): MenuSyntheticEvent {\n let defaultPrevented = nativeEvent.defaultPrevented\n let propagationStopped = false\n const syntheticEvent = Object.create(nativeEvent)\n\n Object.defineProperties(syntheticEvent, {\n nativeEvent: { value: nativeEvent },\n currentTarget: { value: element },\n target: { value: nativeEvent.target },\n persist: { value: () => undefined },\n isDefaultPrevented: { value: () => defaultPrevented },\n isPropagationStopped: { value: () => propagationStopped },\n preventDefault: {\n value: () => {\n defaultPrevented = true\n nativeEvent.preventDefault()\n },\n },\n stopPropagation: {\n value: () => {\n propagationStopped = true\n nativeEvent.stopPropagation()\n },\n },\n })\n\n return syntheticEvent as MenuSyntheticEvent\n}\n\nfunction isDirectPropertyKey(key: string) {\n return DIRECT_PROPERTY_KEYS.has(key)\n}\n\nfunction setDirectProperty(element: HTMLDivElement, key: string, value: unknown) {\n if (key === 'tabIndex') {\n element.tabIndex = Number(value)\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = value\n}\n\nfunction clearDirectProperty(element: HTMLDivElement, key: string) {\n if (key === 'tabIndex') {\n element.removeAttribute('tabindex')\n return\n }\n\n const propertyValue = (element as unknown as Record<string, unknown>)[key]\n\n if (typeof propertyValue === 'boolean') {\n ;(element as unknown as Record<string, unknown>)[key] = false\n return\n }\n\n if (typeof propertyValue === 'number') {\n ;(element as unknown as Record<string, unknown>)[key] = 0\n return\n }\n\n ;(element as unknown as Record<string, unknown>)[key] = ''\n}\n\nfunction toStyleValue(styleName: string, value: string | number) {\n if (\n typeof value !== 'number' ||\n value === 0 ||\n styleName.startsWith('--') ||\n UNITLESS_STYLE_PROPERTIES.has(styleName)\n ) {\n return String(value)\n }\n\n return `${value}px`\n}\n\nfunction removeStyleProperty(element: HTMLDivElement, styleName: string) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.removeProperty(toStylePropertyName(styleName))\n}\n\nfunction applyStyleProperty(element: HTMLDivElement, styleName: string, value: string | number) {\n if (PLUGIN_MANAGED_STYLE_PROPERTIES.has(styleName)) {\n return\n }\n\n element.style.setProperty(toStylePropertyName(styleName), toStyleValue(styleName, value))\n}\n\nfunction syncAttributes(\n element: HTMLDivElement,\n prevProps: MenuElementProps,\n nextProps: MenuElementProps,\n) {\n const allKeys = new Set([...Object.keys(prevProps), ...Object.keys(nextProps)])\n\n allKeys.forEach(key => {\n if (\n ATTRIBUTE_EXCLUSIONS.has(key) ||\n !isForwardedAttributeKey(key) ||\n isEventProp(key, prevProps[key as keyof MenuElementProps]) ||\n isEventProp(key, nextProps[key as keyof MenuElementProps])\n ) {\n return\n }\n\n const prevValue = prevProps[key as keyof MenuElementProps]\n const nextValue = nextProps[key as keyof MenuElementProps]\n\n if (prevValue === nextValue) {\n return\n }\n\n const attributeName = toAttributeName(key)\n\n if (nextValue == null || nextValue === false) {\n if (isDirectPropertyKey(key)) {\n clearDirectProperty(element, key)\n }\n\n element.removeAttribute(attributeName)\n return\n }\n\n if (nextValue === true) {\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, true)\n }\n\n element.setAttribute(attributeName, '')\n return\n }\n\n if (isDirectPropertyKey(key)) {\n setDirectProperty(element, key, nextValue)\n return\n }\n\n element.setAttribute(attributeName, String(nextValue))\n })\n}\n\nfunction syncClassName(element: HTMLDivElement, prevClassName?: string, nextClassName?: string) {\n if (prevClassName === nextClassName) {\n return\n }\n\n if (nextClassName) {\n element.className = nextClassName\n return\n }\n\n element.removeAttribute('class')\n}\n\nfunction syncStyles(\n element: HTMLDivElement,\n prevStyle: CSSProperties | undefined,\n nextStyle: CSSProperties | undefined,\n) {\n const previousStyle = prevStyle ?? {}\n const currentStyle = nextStyle ?? {}\n const allStyleNames = new Set([...Object.keys(previousStyle), ...Object.keys(currentStyle)])\n\n allStyleNames.forEach(styleName => {\n const prevValue = previousStyle[styleName as keyof CSSProperties]\n const nextValue = currentStyle[styleName as keyof CSSProperties]\n\n if (prevValue === nextValue) {\n return\n }\n\n if (nextValue == null) {\n removeStyleProperty(element, styleName)\n return\n }\n\n applyStyleProperty(element, styleName, nextValue as string | number)\n })\n}\n\nfunction syncEventListeners(\n element: HTMLDivElement,\n prevListeners: EventListenerEntry[],\n nextProps: MenuElementProps,\n) {\n prevListeners.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n\n const nextListeners: EventListenerEntry[] = []\n\n Object.entries(nextProps).forEach(([key, value]) => {\n if (!isEventProp(key, value)) {\n return\n }\n\n const { eventName, options } = toEventConfig(key)\n const listener: MenuNativeListener = event => {\n value(createSyntheticEvent(element, event))\n }\n\n element.addEventListener(eventName, listener, options)\n nextListeners.push({ eventName, listener, options })\n })\n\n return nextListeners\n}\n\nexport function useMenuElementProps(element: HTMLDivElement, props: MenuElementProps) {\n const previousPropsRef = useRef<MenuElementProps>({})\n const listenersRef = useRef<EventListenerEntry[]>([])\n\n useIsomorphicLayoutEffect(() => {\n const previousProps = previousPropsRef.current\n\n syncClassName(element, previousProps.className, props.className)\n syncStyles(element, previousProps.style, props.style)\n syncAttributes(element, previousProps, props)\n listenersRef.current = syncEventListeners(element, listenersRef.current, props)\n previousPropsRef.current = props\n\n return () => {\n listenersRef.current.forEach(({ eventName, listener, options }) => {\n element.removeEventListener(eventName, listener, options)\n })\n listenersRef.current = []\n }\n }, [element, props])\n}\n","import type { FloatingMenuPluginProps } from '@tiptap/extension-floating-menu'\nimport { FloatingMenuPlugin } from '@tiptap/extension-floating-menu'\nimport type { PluginKey } from '@tiptap/pm/state'\nimport { useCurrentEditor } from '@tiptap/react'\nimport React, { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { getAutoPluginKey } from './getAutoPluginKey.js'\nimport { useMenuElementProps } from './useMenuElementProps.js'\n\ntype Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>\n\nexport type FloatingMenuProps = Omit<\n Optional<FloatingMenuPluginProps, 'pluginKey'>,\n 'element' | 'editor'\n> & {\n editor: FloatingMenuPluginProps['editor'] | null\n options?: FloatingMenuPluginProps['options']\n} & React.HTMLAttributes<HTMLDivElement>\n\nexport const FloatingMenu = React.forwardRef<HTMLDivElement, FloatingMenuProps>(\n (\n {\n pluginKey,\n editor,\n updateDelay,\n resizeDelay,\n appendTo,\n shouldShow = null,\n options,\n children,\n ...restProps\n },\n ref,\n ) => {\n const menuEl = useRef(document.createElement('div'))\n const resolvedPluginKey = useRef<PluginKey | string>(\n getAutoPluginKey(pluginKey, 'floatingMenu'),\n ).current\n\n useMenuElementProps(menuEl.current, restProps)\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 floating 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 floatingMenuPluginProps: Omit<FloatingMenuPluginProps, 'editor' | 'element'> = {\n updateDelay,\n resizeDelay,\n appendTo,\n pluginKey: resolvedPluginKey,\n shouldShow,\n options,\n }\n\n /**\n * The props for the floating 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 floatingMenuPluginPropsRef = useRef(floatingMenuPluginProps)\n floatingMenuPluginPropsRef.current = floatingMenuPluginProps\n\n /**\n * Track whether the plugin has been initialized, so we only send updates\n * after the initial registration.\n */\n const [pluginInitialized, setPluginInitialized] = useState(false)\n\n /**\n * Track whether we need to skip the first options update dispatch.\n * This prevents unnecessary updates right after plugin initialization.\n */\n const skipFirstUpdateRef = useRef(true)\n\n useEffect(() => {\n if (pluginEditor?.isDestroyed) {\n return\n }\n\n if (!pluginEditor) {\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 floatingMenuElement = menuEl.current\n floatingMenuElement.style.visibility = 'hidden'\n floatingMenuElement.style.position = 'absolute'\n\n const plugin = FloatingMenuPlugin({\n ...floatingMenuPluginPropsRef.current,\n editor: pluginEditor,\n element: floatingMenuElement,\n })\n\n pluginEditor.registerPlugin(plugin)\n\n const createdPluginKey = floatingMenuPluginPropsRef.current.pluginKey\n\n skipFirstUpdateRef.current = true\n setPluginInitialized(true)\n\n return () => {\n setPluginInitialized(false)\n pluginEditor.unregisterPlugin(createdPluginKey)\n window.requestAnimationFrame(() => {\n if (floatingMenuElement.parentNode) {\n floatingMenuElement.parentNode.removeChild(floatingMenuElement)\n }\n })\n }\n }, [pluginEditor])\n\n /**\n * Update the plugin options when props change after the plugin has been initialized.\n * This allows dynamic updates to options like scrollTarget without re-registering the entire plugin.\n */\n useEffect(() => {\n if (!pluginInitialized || !pluginEditor || pluginEditor.isDestroyed) {\n return\n }\n\n // Skip the first update right after initialization since the plugin was just created with these options\n if (skipFirstUpdateRef.current) {\n skipFirstUpdateRef.current = false\n return\n }\n\n pluginEditor.view.dispatch(\n pluginEditor.state.tr.setMeta(resolvedPluginKey, {\n type: 'updateOptions',\n options: floatingMenuPluginPropsRef.current,\n }),\n )\n }, [\n pluginInitialized,\n pluginEditor,\n updateDelay,\n resizeDelay,\n shouldShow,\n options,\n appendTo,\n resolvedPluginKey,\n ])\n\n return createPortal(children, menuEl.current)\n },\n)\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","useCurrentEditor","React","useEffect","useRef","useState","createPortal","React","useRef","useCurrentEditor","useState","useEffect","createPortal"]} |
+7
-7
| { | ||
| "name": "@tiptap/react", | ||
| "version": "3.27.3", | ||
| "version": "3.27.4", | ||
| "description": "React components for tiptap", | ||
@@ -60,4 +60,4 @@ "keywords": [ | ||
| "react-dom": "^19.0.0", | ||
| "@tiptap/core": "^3.27.3", | ||
| "@tiptap/pm": "^3.27.3" | ||
| "@tiptap/core": "^3.27.4", | ||
| "@tiptap/pm": "^3.27.4" | ||
| }, | ||
@@ -69,8 +69,8 @@ "peerDependencies": { | ||
| "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", | ||
| "@tiptap/core": "3.27.3", | ||
| "@tiptap/pm": "3.27.3" | ||
| "@tiptap/core": "3.27.4", | ||
| "@tiptap/pm": "3.27.4" | ||
| }, | ||
| "optionalDependencies": { | ||
| "@tiptap/extension-bubble-menu": "^3.27.3", | ||
| "@tiptap/extension-floating-menu": "^3.27.3" | ||
| "@tiptap/extension-bubble-menu": "^3.27.4", | ||
| "@tiptap/extension-floating-menu": "^3.27.4" | ||
| }, | ||
@@ -77,0 +77,0 @@ "scripts": { |
+2
-0
@@ -0,1 +1,3 @@ | ||
| 'use client' | ||
| export * from './Context.js' | ||
@@ -2,0 +4,0 @@ export * from './EditorContent.js' |
@@ -0,2 +1,4 @@ | ||
| 'use client' | ||
| export * from './BubbleMenu.js' | ||
| export * from './FloatingMenu.js' |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
476149
0.22%37
2.78%6680
0.41%4
33.33%