(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/extension-bubble-menu'), require('react'), require('react-dom'), require('@tiptap/core'), require('@tiptap/extension-floating-menu')) :
	typeof define === 'function' && define.amd ? define(['exports', '@tiptap/extension-bubble-menu', 'react', 'react-dom', '@tiptap/core', '@tiptap/extension-floating-menu'], factory) :
	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/react"] = {}, global.extensionBubbleMenu, global.React, global.ReactDOM, global.core, global.extensionFloatingMenu));
})(this, (function (exports, extensionBubbleMenu, React, ReactDOM, core, extensionFloatingMenu) { 'use strict';

	function getDefaultExportFromCjs (x) {
		return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
	}

	var shim = {exports: {}};

	var useSyncExternalStoreShim_production_min = {};

	/**
	 * @license React
	 * use-sync-external-store-shim.production.min.js
	 *
	 * Copyright (c) Facebook, Inc. and its affiliates.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	var hasRequiredUseSyncExternalStoreShim_production_min;

	function requireUseSyncExternalStoreShim_production_min () {
		if (hasRequiredUseSyncExternalStoreShim_production_min) return useSyncExternalStoreShim_production_min;
		hasRequiredUseSyncExternalStoreShim_production_min = 1;
	var e=React;function h(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}var k="function"===typeof Object.is?Object.is:h,l=e.useState,m=e.useEffect,n=e.useLayoutEffect,p=e.useDebugValue;function q(a,b){var d=b(),f=l({inst:{value:d,getSnapshot:b}}),c=f[0].inst,g=f[1];n(function(){c.value=d;c.getSnapshot=b;r(c)&&g({inst:c});},[a,d,b]);m(function(){r(c)&&g({inst:c});return a(function(){r(c)&&g({inst:c});})},[a]);p(d);return d}
		function r(a){var b=a.getSnapshot;a=a.value;try{var d=b();return !k(a,d)}catch(f){return !0}}function t(a,b){return b()}var u="undefined"===typeof window||"undefined"===typeof window.document||"undefined"===typeof window.document.createElement?t:q;useSyncExternalStoreShim_production_min.useSyncExternalStore=void 0!==e.useSyncExternalStore?e.useSyncExternalStore:u;
		return useSyncExternalStoreShim_production_min;
	}

	var useSyncExternalStoreShim_development = {};

	/**
	 * @license React
	 * use-sync-external-store-shim.development.js
	 *
	 * Copyright (c) Facebook, Inc. and its affiliates.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	var hasRequiredUseSyncExternalStoreShim_development;

	function requireUseSyncExternalStoreShim_development () {
		if (hasRequiredUseSyncExternalStoreShim_development) return useSyncExternalStoreShim_development;
		hasRequiredUseSyncExternalStoreShim_development = 1;

		if (process.env.NODE_ENV !== "production") {
		  (function() {

		/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
		if (
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===
		    'function'
		) {
		  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
		}
		          var React$1 = React;

		var ReactSharedInternals = React$1.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

		function error(format) {
		  {
		    {
		      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
		        args[_key2 - 1] = arguments[_key2];
		      }

		      printWarning('error', format, args);
		    }
		  }
		}

		function printWarning(level, format, args) {
		  // When changing this logic, you might want to also
		  // update consoleWithStackDev.www.js as well.
		  {
		    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
		    var stack = ReactDebugCurrentFrame.getStackAddendum();

		    if (stack !== '') {
		      format += '%s';
		      args = args.concat([stack]);
		    } // eslint-disable-next-line react-internal/safe-string-coercion


		    var argsWithFormat = args.map(function (item) {
		      return String(item);
		    }); // Careful: RN currently depends on this prefix

		    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
		    // breaks IE9: https://github.com/facebook/react/issues/13610
		    // eslint-disable-next-line react-internal/no-production-logging

		    Function.prototype.apply.call(console[level], console, argsWithFormat);
		  }
		}

		/**
		 * inlined Object.is polyfill to avoid requiring consumers ship their own
		 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
		 */
		function is(x, y) {
		  return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
		  ;
		}

		var objectIs = typeof Object.is === 'function' ? Object.is : is;

		// dispatch for CommonJS interop named imports.

		var useState = React$1.useState,
		    useEffect = React$1.useEffect,
		    useLayoutEffect = React$1.useLayoutEffect,
		    useDebugValue = React$1.useDebugValue;
		var didWarnOld18Alpha = false;
		var didWarnUncachedGetSnapshot = false; // Disclaimer: This shim breaks many of the rules of React, and only works
		// because of a very particular set of implementation details and assumptions
		// -- change any one of them and it will break. The most important assumption
		// is that updates are always synchronous, because concurrent rendering is
		// only available in versions of React that also have a built-in
		// useSyncExternalStore API. And we only use this shim when the built-in API
		// does not exist.
		//
		// Do not assume that the clever hacks used by this hook also work in general.
		// The point of this shim is to replace the need for hacks by other libraries.

		function useSyncExternalStore(subscribe, getSnapshot, // Note: The shim does not use getServerSnapshot, because pre-18 versions of
		// React do not expose a way to check if we're hydrating. So users of the shim
		// will need to track that themselves and return the correct value
		// from `getSnapshot`.
		getServerSnapshot) {
		  {
		    if (!didWarnOld18Alpha) {
		      if (React$1.startTransition !== undefined) {
		        didWarnOld18Alpha = true;

		        error('You are using an outdated, pre-release alpha of React 18 that ' + 'does not support useSyncExternalStore. The ' + 'use-sync-external-store shim will not work correctly. Upgrade ' + 'to a newer pre-release.');
		      }
		    }
		  } // Read the current snapshot from the store on every render. Again, this
		  // breaks the rules of React, and only works here because of specific
		  // implementation details, most importantly that updates are
		  // always synchronous.


		  var value = getSnapshot();

		  {
		    if (!didWarnUncachedGetSnapshot) {
		      var cachedValue = getSnapshot();

		      if (!objectIs(value, cachedValue)) {
		        error('The result of getSnapshot should be cached to avoid an infinite loop');

		        didWarnUncachedGetSnapshot = true;
		      }
		    }
		  } // Because updates are synchronous, we don't queue them. Instead we force a
		  // re-render whenever the subscribed state changes by updating an some
		  // arbitrary useState hook. Then, during render, we call getSnapshot to read
		  // the current value.
		  //
		  // Because we don't actually use the state returned by the useState hook, we
		  // can save a bit of memory by storing other stuff in that slot.
		  //
		  // To implement the early bailout, we need to track some things on a mutable
		  // object. Usually, we would put that in a useRef hook, but we can stash it in
		  // our useState hook instead.
		  //
		  // To force a re-render, we call forceUpdate({inst}). That works because the
		  // new object always fails an equality check.


		  var _useState = useState({
		    inst: {
		      value: value,
		      getSnapshot: getSnapshot
		    }
		  }),
		      inst = _useState[0].inst,
		      forceUpdate = _useState[1]; // Track the latest getSnapshot function with a ref. This needs to be updated
		  // in the layout phase so we can access it during the tearing check that
		  // happens on subscribe.


		  useLayoutEffect(function () {
		    inst.value = value;
		    inst.getSnapshot = getSnapshot; // Whenever getSnapshot or subscribe changes, we need to check in the
		    // commit phase if there was an interleaved mutation. In concurrent mode
		    // this can happen all the time, but even in synchronous mode, an earlier
		    // effect may have mutated the store.

		    if (checkIfSnapshotChanged(inst)) {
		      // Force a re-render.
		      forceUpdate({
		        inst: inst
		      });
		    }
		  }, [subscribe, value, getSnapshot]);
		  useEffect(function () {
		    // Check for changes right before subscribing. Subsequent changes will be
		    // detected in the subscription handler.
		    if (checkIfSnapshotChanged(inst)) {
		      // Force a re-render.
		      forceUpdate({
		        inst: inst
		      });
		    }

		    var handleStoreChange = function () {
		      // TODO: Because there is no cross-renderer API for batching updates, it's
		      // up to the consumer of this library to wrap their subscription event
		      // with unstable_batchedUpdates. Should we try to detect when this isn't
		      // the case and print a warning in development?
		      // The store changed. Check if the snapshot changed since the last time we
		      // read from the store.
		      if (checkIfSnapshotChanged(inst)) {
		        // Force a re-render.
		        forceUpdate({
		          inst: inst
		        });
		      }
		    }; // Subscribe to the store and return a clean-up function.


		    return subscribe(handleStoreChange);
		  }, [subscribe]);
		  useDebugValue(value);
		  return value;
		}

		function checkIfSnapshotChanged(inst) {
		  var latestGetSnapshot = inst.getSnapshot;
		  var prevValue = inst.value;

		  try {
		    var nextValue = latestGetSnapshot();
		    return !objectIs(prevValue, nextValue);
		  } catch (error) {
		    return true;
		  }
		}

		function useSyncExternalStore$1(subscribe, getSnapshot, getServerSnapshot) {
		  // Note: The shim does not use getServerSnapshot, because pre-18 versions of
		  // React do not expose a way to check if we're hydrating. So users of the shim
		  // will need to track that themselves and return the correct value
		  // from `getSnapshot`.
		  return getSnapshot();
		}

		var canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined');

		var isServerEnvironment = !canUseDOM;

		var shim = isServerEnvironment ? useSyncExternalStore$1 : useSyncExternalStore;
		var useSyncExternalStore$2 = React$1.useSyncExternalStore !== undefined ? React$1.useSyncExternalStore : shim;

		useSyncExternalStoreShim_development.useSyncExternalStore = useSyncExternalStore$2;
		          /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
		if (
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===
		    'function'
		) {
		  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());
		}
		        
		  })();
		}
		return useSyncExternalStoreShim_development;
	}

	if (process.env.NODE_ENV === 'production') {
	  shim.exports = requireUseSyncExternalStoreShim_production_min();
	} else {
	  shim.exports = requireUseSyncExternalStoreShim_development();
	}

	var shimExports = shim.exports;

	const mergeRefs = (...refs) => {
	    return (node) => {
	        refs.forEach(ref => {
	            if (typeof ref === 'function') {
	                ref(node);
	            }
	            else if (ref) {
	                ref.current = node;
	            }
	        });
	    };
	};
	/**
	 * This component renders all of the editor's node views.
	 */
	const Portals = ({ contentComponent, }) => {
	    // For performance reasons, we render the node view portals on state changes only
	    const renderers = shimExports.useSyncExternalStore(contentComponent.subscribe, contentComponent.getSnapshot, contentComponent.getServerSnapshot);
	    // This allows us to directly render the portals without any additional wrapper
	    return (React.createElement(React.Fragment, null, Object.values(renderers)));
	};
	function getInstance() {
	    const subscribers = new Set();
	    let renderers = {};
	    return {
	        /**
	         * Subscribe to the editor instance's changes.
	         */
	        subscribe(callback) {
	            subscribers.add(callback);
	            return () => {
	                subscribers.delete(callback);
	            };
	        },
	        getSnapshot() {
	            return renderers;
	        },
	        getServerSnapshot() {
	            return renderers;
	        },
	        /**
	         * Adds a new NodeView Renderer to the editor.
	         */
	        setRenderer(id, renderer) {
	            renderers = {
	                ...renderers,
	                [id]: ReactDOM.createPortal(renderer.reactElement, renderer.element, id),
	            };
	            subscribers.forEach(subscriber => subscriber());
	        },
	        /**
	         * Removes a NodeView Renderer from the editor.
	         */
	        removeRenderer(id) {
	            const nextRenderers = { ...renderers };
	            delete nextRenderers[id];
	            renderers = nextRenderers;
	            subscribers.forEach(subscriber => subscriber());
	        },
	    };
	}
	class PureEditorContent extends React.Component {
	    constructor(props) {
	        var _a;
	        super(props);
	        this.editorContentRef = React.createRef();
	        this.initialized = false;
	        this.state = {
	            hasContentComponentInitialized: Boolean((_a = props.editor) === null || _a === void 0 ? void 0 : _a.contentComponent),
	        };
	    }
	    componentDidMount() {
	        this.init();
	    }
	    componentDidUpdate() {
	        this.init();
	    }
	    init() {
	        const editor = this.props.editor;
	        if (editor && !editor.isDestroyed && editor.options.element) {
	            if (editor.contentComponent) {
	                return;
	            }
	            const element = this.editorContentRef.current;
	            element.append(...editor.options.element.childNodes);
	            editor.setOptions({
	                element,
	            });
	            editor.contentComponent = getInstance();
	            // Has the content component been initialized?
	            if (!this.state.hasContentComponentInitialized) {
	                // Subscribe to the content component
	                this.unsubscribeToContentComponent = editor.contentComponent.subscribe(() => {
	                    this.setState(prevState => {
	                        if (!prevState.hasContentComponentInitialized) {
	                            return {
	                                hasContentComponentInitialized: true,
	                            };
	                        }
	                        return prevState;
	                    });
	                    // Unsubscribe to previous content component
	                    if (this.unsubscribeToContentComponent) {
	                        this.unsubscribeToContentComponent();
	                    }
	                });
	            }
	            editor.createNodeViews();
	            this.initialized = true;
	        }
	    }
	    componentWillUnmount() {
	        const editor = this.props.editor;
	        if (!editor) {
	            return;
	        }
	        this.initialized = false;
	        if (!editor.isDestroyed) {
	            editor.view.setProps({
	                nodeViews: {},
	            });
	        }
	        if (this.unsubscribeToContentComponent) {
	            this.unsubscribeToContentComponent();
	        }
	        editor.contentComponent = null;
	        if (!editor.options.element.firstChild) {
	            return;
	        }
	        const newElement = document.createElement('div');
	        newElement.append(...editor.options.element.childNodes);
	        editor.setOptions({
	            element: newElement,
	        });
	    }
	    render() {
	        const { editor, innerRef, ...rest } = this.props;
	        return (React.createElement(React.Fragment, null,
	            React.createElement("div", { ref: mergeRefs(innerRef, this.editorContentRef), ...rest }),
	            (editor === null || editor === void 0 ? void 0 : editor.contentComponent) && React.createElement(Portals, { contentComponent: editor.contentComponent })));
	    }
	}
	// EditorContent should be re-created whenever the Editor instance changes
	const EditorContentWithKey = React.forwardRef((props, ref) => {
	    const key = React.useMemo(() => {
	        return Math.floor(Math.random() * 0xffffffff).toString();
	        // eslint-disable-next-line react-hooks/exhaustive-deps
	    }, [props.editor]);
	    // Can't use JSX here because it conflicts with the type definition of Vue's JSX, so use createElement
	    return React.createElement(PureEditorContent, {
	        key,
	        innerRef: ref,
	        ...props,
	    });
	});
	const EditorContent = React.memo(EditorContentWithKey);

	var react = function equal(a, b) {
	  if (a === b) return true;

	  if (a && b && typeof a == 'object' && typeof b == 'object') {
	    if (a.constructor !== b.constructor) return false;

	    var length, i, keys;
	    if (Array.isArray(a)) {
	      length = a.length;
	      if (length != b.length) return false;
	      for (i = length; i-- !== 0;)
	        if (!equal(a[i], b[i])) return false;
	      return true;
	    }


	    if ((a instanceof Map) && (b instanceof Map)) {
	      if (a.size !== b.size) return false;
	      for (i of a.entries())
	        if (!b.has(i[0])) return false;
	      for (i of a.entries())
	        if (!equal(i[1], b.get(i[0]))) return false;
	      return true;
	    }

	    if ((a instanceof Set) && (b instanceof Set)) {
	      if (a.size !== b.size) return false;
	      for (i of a.entries())
	        if (!b.has(i[0])) return false;
	      return true;
	    }

	    if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
	      length = a.length;
	      if (length != b.length) return false;
	      for (i = length; i-- !== 0;)
	        if (a[i] !== b[i]) return false;
	      return true;
	    }


	    if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
	    if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
	    if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

	    keys = Object.keys(a);
	    length = keys.length;
	    if (length !== Object.keys(b).length) return false;

	    for (i = length; i-- !== 0;)
	      if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;

	    for (i = length; i-- !== 0;) {
	      var key = keys[i];

	      if (key === '_owner' && a.$$typeof) {
	        // React-specific: avoid traversing React elements' _owner.
	        //  _owner contains circular references
	        // and is not needed when comparing the actual elements (and not their owners)
	        continue;
	      }

	      if (!equal(a[key], b[key])) return false;
	    }

	    return true;
	  }

	  // true if both NaN, false otherwise
	  return a!==a && b!==b;
	};

	var deepEqual = /*@__PURE__*/getDefaultExportFromCjs(react);

	var withSelector = {exports: {}};

	var withSelector_production_min = {};

	/**
	 * @license React
	 * use-sync-external-store-shim/with-selector.production.min.js
	 *
	 * Copyright (c) Facebook, Inc. and its affiliates.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	var hasRequiredWithSelector_production_min;

	function requireWithSelector_production_min () {
		if (hasRequiredWithSelector_production_min) return withSelector_production_min;
		hasRequiredWithSelector_production_min = 1;
	var h=React,n=shimExports;function p(a,b){return a===b&&(0!==a||1/a===1/b)||a!==a&&b!==b}var q="function"===typeof Object.is?Object.is:p,r=n.useSyncExternalStore,t=h.useRef,u=h.useEffect,v=h.useMemo,w=h.useDebugValue;
		withSelector_production_min.useSyncExternalStoreWithSelector=function(a,b,e,l,g){var c=t(null);if(null===c.current){var f={hasValue:!1,value:null};c.current=f;}else f=c.current;c=v(function(){function a(a){if(!c){c=!0;d=a;a=l(a);if(void 0!==g&&f.hasValue){var b=f.value;if(g(b,a))return k=b}return k=a}b=k;if(q(d,a))return b;var e=l(a);if(void 0!==g&&g(b,e))return b;d=a;return k=e}var c=!1,d,k,m=void 0===e?null:e;return [function(){return a(b())},null===m?void 0:function(){return a(m())}]},[b,e,l,g]);var d=r(a,c[0],c[1]);
		u(function(){f.hasValue=!0;f.value=d;},[d]);w(d);return d};
		return withSelector_production_min;
	}

	var withSelector_development = {};

	/**
	 * @license React
	 * use-sync-external-store-shim/with-selector.development.js
	 *
	 * Copyright (c) Facebook, Inc. and its affiliates.
	 *
	 * This source code is licensed under the MIT license found in the
	 * LICENSE file in the root directory of this source tree.
	 */

	var hasRequiredWithSelector_development;

	function requireWithSelector_development () {
		if (hasRequiredWithSelector_development) return withSelector_development;
		hasRequiredWithSelector_development = 1;

		if (process.env.NODE_ENV !== "production") {
		  (function() {

		/* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
		if (
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart ===
		    'function'
		) {
		  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error());
		}
		          var React$1 = React;
		var shim = shimExports;

		/**
		 * inlined Object.is polyfill to avoid requiring consumers ship their own
		 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
		 */
		function is(x, y) {
		  return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y // eslint-disable-line no-self-compare
		  ;
		}

		var objectIs = typeof Object.is === 'function' ? Object.is : is;

		var useSyncExternalStore = shim.useSyncExternalStore;

		// for CommonJS interop.

		var useRef = React$1.useRef,
		    useEffect = React$1.useEffect,
		    useMemo = React$1.useMemo,
		    useDebugValue = React$1.useDebugValue; // Same as useSyncExternalStore, but supports selector and isEqual arguments.

		function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
		  // Use this to track the rendered snapshot.
		  var instRef = useRef(null);
		  var inst;

		  if (instRef.current === null) {
		    inst = {
		      hasValue: false,
		      value: null
		    };
		    instRef.current = inst;
		  } else {
		    inst = instRef.current;
		  }

		  var _useMemo = useMemo(function () {
		    // Track the memoized state using closure variables that are local to this
		    // memoized instance of a getSnapshot function. Intentionally not using a
		    // useRef hook, because that state would be shared across all concurrent
		    // copies of the hook/component.
		    var hasMemo = false;
		    var memoizedSnapshot;
		    var memoizedSelection;

		    var memoizedSelector = function (nextSnapshot) {
		      if (!hasMemo) {
		        // The first time the hook is called, there is no memoized result.
		        hasMemo = true;
		        memoizedSnapshot = nextSnapshot;

		        var _nextSelection = selector(nextSnapshot);

		        if (isEqual !== undefined) {
		          // Even if the selector has changed, the currently rendered selection
		          // may be equal to the new selection. We should attempt to reuse the
		          // current value if possible, to preserve downstream memoizations.
		          if (inst.hasValue) {
		            var currentSelection = inst.value;

		            if (isEqual(currentSelection, _nextSelection)) {
		              memoizedSelection = currentSelection;
		              return currentSelection;
		            }
		          }
		        }

		        memoizedSelection = _nextSelection;
		        return _nextSelection;
		      } // We may be able to reuse the previous invocation's result.


		      // We may be able to reuse the previous invocation's result.
		      var prevSnapshot = memoizedSnapshot;
		      var prevSelection = memoizedSelection;

		      if (objectIs(prevSnapshot, nextSnapshot)) {
		        // The snapshot is the same as last time. Reuse the previous selection.
		        return prevSelection;
		      } // The snapshot has changed, so we need to compute a new selection.


		      // The snapshot has changed, so we need to compute a new selection.
		      var nextSelection = selector(nextSnapshot); // If a custom isEqual function is provided, use that to check if the data
		      // has changed. If it hasn't, return the previous selection. That signals
		      // to React that the selections are conceptually equal, and we can bail
		      // out of rendering.

		      // If a custom isEqual function is provided, use that to check if the data
		      // has changed. If it hasn't, return the previous selection. That signals
		      // to React that the selections are conceptually equal, and we can bail
		      // out of rendering.
		      if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
		        return prevSelection;
		      }

		      memoizedSnapshot = nextSnapshot;
		      memoizedSelection = nextSelection;
		      return nextSelection;
		    }; // Assigning this to a constant so that Flow knows it can't change.


		    // Assigning this to a constant so that Flow knows it can't change.
		    var maybeGetServerSnapshot = getServerSnapshot === undefined ? null : getServerSnapshot;

		    var getSnapshotWithSelector = function () {
		      return memoizedSelector(getSnapshot());
		    };

		    var getServerSnapshotWithSelector = maybeGetServerSnapshot === null ? undefined : function () {
		      return memoizedSelector(maybeGetServerSnapshot());
		    };
		    return [getSnapshotWithSelector, getServerSnapshotWithSelector];
		  }, [getSnapshot, getServerSnapshot, selector, isEqual]),
		      getSelection = _useMemo[0],
		      getServerSelection = _useMemo[1];

		  var value = useSyncExternalStore(subscribe, getSelection, getServerSelection);
		  useEffect(function () {
		    inst.hasValue = true;
		    inst.value = value;
		  }, [value]);
		  useDebugValue(value);
		  return value;
		}

		withSelector_development.useSyncExternalStoreWithSelector = useSyncExternalStoreWithSelector;
		          /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
		if (
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
		  typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop ===
		    'function'
		) {
		  __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error());
		}
		        
		  })();
		}
		return withSelector_development;
	}

	if (process.env.NODE_ENV === 'production') {
	  withSelector.exports = requireWithSelector_production_min();
	} else {
	  withSelector.exports = requireWithSelector_development();
	}

	var withSelectorExports = withSelector.exports;

	const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
	/**
	 * To synchronize the editor instance with the component state,
	 * we need to create a separate instance that is not affected by the component re-renders.
	 */
	class EditorStateManager {
	    constructor(initialEditor) {
	        this.transactionNumber = 0;
	        this.lastTransactionNumber = 0;
	        this.subscribers = new Set();
	        this.editor = initialEditor;
	        this.lastSnapshot = { editor: initialEditor, transactionNumber: 0 };
	        this.getSnapshot = this.getSnapshot.bind(this);
	        this.getServerSnapshot = this.getServerSnapshot.bind(this);
	        this.watch = this.watch.bind(this);
	        this.subscribe = this.subscribe.bind(this);
	    }
	    /**
	     * Get the current editor instance.
	     */
	    getSnapshot() {
	        if (this.transactionNumber === this.lastTransactionNumber) {
	            return this.lastSnapshot;
	        }
	        this.lastTransactionNumber = this.transactionNumber;
	        this.lastSnapshot = { editor: this.editor, transactionNumber: this.transactionNumber };
	        return this.lastSnapshot;
	    }
	    /**
	     * Always disable the editor on the server-side.
	     */
	    getServerSnapshot() {
	        return { editor: null, transactionNumber: 0 };
	    }
	    /**
	     * Subscribe to the editor instance's changes.
	     */
	    subscribe(callback) {
	        this.subscribers.add(callback);
	        return () => {
	            this.subscribers.delete(callback);
	        };
	    }
	    /**
	     * Watch the editor instance for changes.
	     */
	    watch(nextEditor) {
	        this.editor = nextEditor;
	        if (this.editor) {
	            /**
	             * This will force a re-render when the editor state changes.
	             * This is to support things like `editor.can().toggleBold()` in components that `useEditor`.
	             * This could be more efficient, but it's a good trade-off for now.
	             */
	            const fn = () => {
	                this.transactionNumber += 1;
	                this.subscribers.forEach(callback => callback());
	            };
	            const currentEditor = this.editor;
	            currentEditor.on('transaction', fn);
	            return () => {
	                currentEditor.off('transaction', fn);
	            };
	        }
	        return undefined;
	    }
	}
	/**
	 * This hook allows you to watch for changes on the editor instance.
	 * It will allow you to select a part of the editor state and re-render the component when it changes.
	 * @example
	 * ```tsx
	 * const editor = useEditor({...options})
	 * const { currentSelection } = useEditorState({
	 *  editor,
	 *  selector: snapshot => ({ currentSelection: snapshot.editor.state.selection }),
	 * })
	 */
	function useEditorState(options) {
	    var _a;
	    const [editorStateManager] = React.useState(() => new EditorStateManager(options.editor));
	    // Using the `useSyncExternalStore` hook to sync the editor instance with the component state
	    const selectedState = withSelectorExports.useSyncExternalStoreWithSelector(editorStateManager.subscribe, editorStateManager.getSnapshot, editorStateManager.getServerSnapshot, options.selector, (_a = options.equalityFn) !== null && _a !== void 0 ? _a : deepEqual);
	    useIsomorphicLayoutEffect(() => {
	        return editorStateManager.watch(options.editor);
	    }, [options.editor, editorStateManager]);
	    React.useDebugValue(selectedState);
	    return selectedState;
	}

	const isDev = process.env.NODE_ENV !== 'production';
	const isSSR = typeof window === 'undefined';
	const isNext = isSSR || Boolean(typeof window !== 'undefined' && window.next);
	/**
	 * This class handles the creation, destruction, and re-creation of the editor instance.
	 */
	class EditorInstanceManager {
	    constructor(options) {
	        /**
	         * The current editor instance.
	         */
	        this.editor = null;
	        /**
	         * The subscriptions to notify when the editor instance
	         * has been created or destroyed.
	         */
	        this.subscriptions = new Set();
	        /**
	         * Whether the editor has been mounted.
	         */
	        this.isComponentMounted = false;
	        /**
	         * The most recent dependencies array.
	         */
	        this.previousDeps = null;
	        /**
	         * The unique instance ID. This is used to identify the editor instance. And will be re-generated for each new instance.
	         */
	        this.instanceId = '';
	        this.options = options;
	        this.subscriptions = new Set();
	        this.setEditor(this.getInitialEditor());
	        this.scheduleDestroy();
	        this.getEditor = this.getEditor.bind(this);
	        this.getServerSnapshot = this.getServerSnapshot.bind(this);
	        this.subscribe = this.subscribe.bind(this);
	        this.refreshEditorInstance = this.refreshEditorInstance.bind(this);
	        this.scheduleDestroy = this.scheduleDestroy.bind(this);
	        this.onRender = this.onRender.bind(this);
	        this.createEditor = this.createEditor.bind(this);
	    }
	    setEditor(editor) {
	        this.editor = editor;
	        this.instanceId = Math.random().toString(36).slice(2, 9);
	        // Notify all subscribers that the editor instance has been created
	        this.subscriptions.forEach(cb => cb());
	    }
	    getInitialEditor() {
	        if (this.options.current.immediatelyRender === undefined) {
	            if (isSSR || isNext) {
	                // TODO in the next major release, we should throw an error here
	                if (isDev) {
	                    /**
	                     * Throw an error in development, to make sure the developer is aware that tiptap cannot be SSR'd
	                     * and that they need to set `immediatelyRender` to `false` to avoid hydration mismatches.
	                     */
	                    console.warn('Tiptap Error: SSR has been detected, please set `immediatelyRender` explicitly to `false` to avoid hydration mismatches.');
	                }
	                // Best faith effort in production, run the code in the legacy mode to avoid hydration mismatches and errors in production
	                return null;
	            }
	            // Default to immediately rendering when client-side rendering
	            return this.createEditor();
	        }
	        if (this.options.current.immediatelyRender && isSSR && isDev) {
	            // Warn in development, to make sure the developer is aware that tiptap cannot be SSR'd, set `immediatelyRender` to `false` to avoid hydration mismatches.
	            throw new Error('Tiptap Error: SSR has been detected, and `immediatelyRender` has been set to `true` this is an unsupported configuration that may result in errors, explicitly set `immediatelyRender` to `false` to avoid hydration mismatches.');
	        }
	        if (this.options.current.immediatelyRender) {
	            return this.createEditor();
	        }
	        return null;
	    }
	    /**
	     * Create a new editor instance. And attach event listeners.
	     */
	    createEditor() {
	        const optionsToApply = {
	            ...this.options.current,
	            // Always call the most recent version of the callback function by default
	            onBeforeCreate: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onBeforeCreate) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onBlur: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onCreate: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onCreate) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onDestroy: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onDestroy) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onFocus: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onFocus) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onSelectionUpdate: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onSelectionUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onTransaction: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onTransaction) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onUpdate: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onUpdate) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onContentError: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onContentError) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onDrop: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onDrop) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	            onPaste: (...args) => { var _a, _b; return (_b = (_a = this.options.current).onPaste) === null || _b === void 0 ? void 0 : _b.call(_a, ...args); },
	        };
	        const editor = new core.Editor(optionsToApply);
	        // no need to keep track of the event listeners, they will be removed when the editor is destroyed
	        return editor;
	    }
	    /**
	     * Get the current editor instance.
	     */
	    getEditor() {
	        return this.editor;
	    }
	    /**
	     * Always disable the editor on the server-side.
	     */
	    getServerSnapshot() {
	        return null;
	    }
	    /**
	     * Subscribe to the editor instance's changes.
	     */
	    subscribe(onStoreChange) {
	        this.subscriptions.add(onStoreChange);
	        return () => {
	            this.subscriptions.delete(onStoreChange);
	        };
	    }
	    static compareOptions(a, b) {
	        return Object.keys(a).every(key => {
	            if (['onCreate', 'onBeforeCreate', 'onDestroy', 'onUpdate', 'onTransaction', 'onFocus', 'onBlur', 'onSelectionUpdate', 'onContentError', 'onDrop', 'onPaste'].includes(key)) {
	                // we don't want to compare callbacks, they are always different and only registered once
	                return true;
	            }
	            // We often encourage putting extensions inlined in the options object, so we will do a slightly deeper comparison here
	            if (key === 'extensions' && a.extensions && b.extensions) {
	                if (a.extensions.length !== b.extensions.length) {
	                    return false;
	                }
	                return a.extensions.every((extension, index) => {
	                    var _a;
	                    if (extension !== ((_a = b.extensions) === null || _a === void 0 ? void 0 : _a[index])) {
	                        return false;
	                    }
	                    return true;
	                });
	            }
	            if (a[key] !== b[key]) {
	                // if any of the options have changed, we should update the editor options
	                return false;
	            }
	            return true;
	        });
	    }
	    /**
	     * On each render, we will create, update, or destroy the editor instance.
	     * @param deps The dependencies to watch for changes
	     * @returns A cleanup function
	     */
	    onRender(deps) {
	        // The returned callback will run on each render
	        return () => {
	            this.isComponentMounted = true;
	            // Cleanup any scheduled destructions, since we are currently rendering
	            clearTimeout(this.scheduledDestructionTimeout);
	            if (this.editor && !this.editor.isDestroyed && deps.length === 0) {
	                // if the editor does exist & deps are empty, we don't need to re-initialize the editor generally
	                if (!EditorInstanceManager.compareOptions(this.options.current, this.editor.options)) {
	                    // But, the options are different, so we need to update the editor options
	                    // Still, this is faster than re-creating the editor
	                    this.editor.setOptions({
	                        ...this.options.current,
	                        editable: this.editor.isEditable,
	                    });
	                }
	            }
	            else {
	                // When the editor:
	                // - does not yet exist
	                // - is destroyed
	                // - the deps array changes
	                // We need to destroy the editor instance and re-initialize it
	                this.refreshEditorInstance(deps);
	            }
	            return () => {
	                this.isComponentMounted = false;
	                this.scheduleDestroy();
	            };
	        };
	    }
	    /**
	     * Recreate the editor instance if the dependencies have changed.
	     */
	    refreshEditorInstance(deps) {
	        if (this.editor && !this.editor.isDestroyed) {
	            // Editor instance already exists
	            if (this.previousDeps === null) {
	                // If lastDeps has not yet been initialized, reuse the current editor instance
	                this.previousDeps = deps;
	                return;
	            }
	            const depsAreEqual = this.previousDeps.length === deps.length
	                && this.previousDeps.every((dep, index) => dep === deps[index]);
	            if (depsAreEqual) {
	                // deps exist and are equal, no need to recreate
	                return;
	            }
	        }
	        if (this.editor && !this.editor.isDestroyed) {
	            // Destroy the editor instance if it exists
	            this.editor.destroy();
	        }
	        this.setEditor(this.createEditor());
	        // Update the lastDeps to the current deps
	        this.previousDeps = deps;
	    }
	    /**
	     * Schedule the destruction of the editor instance.
	     * This will only destroy the editor if it was not mounted on the next tick.
	     * This is to avoid destroying the editor instance when it's actually still mounted.
	     */
	    scheduleDestroy() {
	        const currentInstanceId = this.instanceId;
	        const currentEditor = this.editor;
	        // Wait two ticks to see if the component is still mounted
	        this.scheduledDestructionTimeout = setTimeout(() => {
	            if (this.isComponentMounted && this.instanceId === currentInstanceId) {
	                // If still mounted on the following tick, with the same instanceId, do not destroy the editor
	                if (currentEditor) {
	                    // just re-apply options as they might have changed
	                    currentEditor.setOptions(this.options.current);
	                }
	                return;
	            }
	            if (currentEditor && !currentEditor.isDestroyed) {
	                currentEditor.destroy();
	                if (this.instanceId === currentInstanceId) {
	                    this.setEditor(null);
	                }
	            }
	            // This allows the effect to run again between ticks
	            // which may save us from having to re-create the editor
	        }, 1);
	    }
	}
	function useEditor(options = {}, deps = []) {
	    const mostRecentOptions = React.useRef(options);
	    mostRecentOptions.current = options;
	    const [instanceManager] = React.useState(() => new EditorInstanceManager(mostRecentOptions));
	    const editor = shimExports.useSyncExternalStore(instanceManager.subscribe, instanceManager.getEditor, instanceManager.getServerSnapshot);
	    React.useDebugValue(editor);
	    // This effect will handle creating/updating the editor instance
	    // eslint-disable-next-line react-hooks/exhaustive-deps
	    React.useEffect(instanceManager.onRender(deps));
	    // The default behavior is to re-render on each transaction
	    // This is legacy behavior that will be removed in future versions
	    useEditorState({
	        editor,
	        selector: ({ transactionNumber }) => {
	            if (options.shouldRerenderOnTransaction === false) {
	                // This will prevent the editor from re-rendering on each transaction
	                return null;
	            }
	            // This will avoid re-rendering on the first transaction when `immediatelyRender` is set to `true`
	            if (options.immediatelyRender && transactionNumber === 0) {
	                return 0;
	            }
	            return transactionNumber + 1;
	        },
	    });
	    return editor;
	}

	const EditorContext = React.createContext({
	    editor: null,
	});
	const EditorConsumer = EditorContext.Consumer;
	/**
	 * A hook to get the current editor instance.
	 */
	const useCurrentEditor = () => React.useContext(EditorContext);
	/**
	 * This is the provider component for the editor.
	 * It allows the editor to be accessible across the entire component tree
	 * with `useCurrentEditor`.
	 */
	function EditorProvider({ children, slotAfter, slotBefore, editorContainerProps = {}, ...editorOptions }) {
	    const editor = useEditor(editorOptions);
	    if (!editor) {
	        return null;
	    }
	    return (React.createElement(EditorContext.Provider, { value: { editor } },
	        slotBefore,
	        React.createElement(EditorConsumer, null, ({ editor: currentEditor }) => (React.createElement(EditorContent, { editor: currentEditor, ...editorContainerProps }))),
	        children,
	        slotAfter));
	}

	const BubbleMenu = (props) => {
	    const [element, setElement] = React.useState(null);
	    const { editor: currentEditor } = useCurrentEditor();
	    React.useEffect(() => {
	        var _a;
	        if (!element) {
	            return;
	        }
	        if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
	            return;
	        }
	        const { pluginKey = 'bubbleMenu', editor, tippyOptions = {}, updateDelay, shouldShow = null, } = props;
	        const menuEditor = editor || currentEditor;
	        if (!menuEditor) {
	            console.warn('BubbleMenu component is not rendered inside of an editor component or does not have editor prop.');
	            return;
	        }
	        const plugin = extensionBubbleMenu.BubbleMenuPlugin({
	            updateDelay,
	            editor: menuEditor,
	            element,
	            pluginKey,
	            shouldShow,
	            tippyOptions,
	        });
	        menuEditor.registerPlugin(plugin);
	        return () => { menuEditor.unregisterPlugin(pluginKey); };
	    }, [props.editor, currentEditor, element]);
	    return (React.createElement("div", { ref: setElement, className: props.className, style: { visibility: 'hidden' } }, props.children));
	};

	const FloatingMenu = (props) => {
	    const [element, setElement] = React.useState(null);
	    const { editor: currentEditor } = useCurrentEditor();
	    React.useEffect(() => {
	        var _a;
	        if (!element) {
	            return;
	        }
	        if (((_a = props.editor) === null || _a === void 0 ? void 0 : _a.isDestroyed) || (currentEditor === null || currentEditor === void 0 ? void 0 : currentEditor.isDestroyed)) {
	            return;
	        }
	        const { pluginKey = 'floatingMenu', editor, tippyOptions = {}, shouldShow = null, } = props;
	        const menuEditor = editor || currentEditor;
	        if (!menuEditor) {
	            console.warn('FloatingMenu component is not rendered inside of an editor component or does not have editor prop.');
	            return;
	        }
	        const plugin = extensionFloatingMenu.FloatingMenuPlugin({
	            pluginKey,
	            editor: menuEditor,
	            element,
	            tippyOptions,
	            shouldShow,
	        });
	        menuEditor.registerPlugin(plugin);
	        return () => { menuEditor.unregisterPlugin(pluginKey); };
	    }, [
	        props.editor,
	        currentEditor,
	        element,
	    ]);
	    return (React.createElement("div", { ref: setElement, className: props.className, style: { visibility: 'hidden' } }, props.children));
	};

	const ReactNodeViewContext = React.createContext({
	    onDragStart: undefined,
	});
	const useReactNodeView = () => React.useContext(ReactNodeViewContext);

	const NodeViewContent = props => {
	    const Tag = props.as || 'div';
	    const { nodeViewContentRef } = useReactNodeView();
	    return (
	    // @ts-ignore
	    React.createElement(Tag, { ...props, ref: nodeViewContentRef, "data-node-view-content": "", style: {
	            whiteSpace: 'pre-wrap',
	            ...props.style,
	        } }));
	};

	const NodeViewWrapper = React.forwardRef((props, ref) => {
	    const { onDragStart } = useReactNodeView();
	    const Tag = props.as || 'div';
	    return (
	    // @ts-ignore
	    React.createElement(Tag, { ...props, ref: ref, "data-node-view-wrapper": "", onDragStart: onDragStart, style: {
	            whiteSpace: 'normal',
	            ...props.style,
	        } }));
	});

	/**
	 * Check if a component is a class component.
	 * @param Component
	 * @returns {boolean}
	 */
	function isClassComponent(Component) {
	    return !!(typeof Component === 'function'
	        && Component.prototype
	        && Component.prototype.isReactComponent);
	}
	/**
	 * Check if a component is a forward ref component.
	 * @param Component
	 * @returns {boolean}
	 */
	function isForwardRefComponent(Component) {
	    return !!(typeof Component === 'object'
	        && Component.$$typeof
	        && (Component.$$typeof.toString() === 'Symbol(react.forward_ref)'
	            || Component.$$typeof.description === 'react.forward_ref'));
	}
	/**
	 * Check if a component is a memoized component.
	 * @param Component
	 * @returns {boolean}
	 */
	function isMemoComponent(Component) {
	    return !!(typeof Component === 'object'
	        && Component.$$typeof
	        && (Component.$$typeof.toString() === 'Symbol(react.memo)' || Component.$$typeof.description === 'react.memo'));
	}
	/**
	 * Check if a component can safely receive a ref prop.
	 * This includes class components, forwardRef components, and memoized components
	 * that wrap forwardRef or class components.
	 * @param Component
	 * @returns {boolean}
	 */
	function canReceiveRef(Component) {
	    // Check if it's a class component
	    if (isClassComponent(Component)) {
	        return true;
	    }
	    // Check if it's a forwardRef component
	    if (isForwardRefComponent(Component)) {
	        return true;
	    }
	    // Check if it's a memoized component
	    if (isMemoComponent(Component)) {
	        // For memoized components, check the wrapped component
	        const wrappedComponent = Component.type;
	        if (wrappedComponent) {
	            return isClassComponent(wrappedComponent) || isForwardRefComponent(wrappedComponent);
	        }
	    }
	    return false;
	}
	/**
	 * Check if we're running React 19+ by detecting if function components support ref props
	 * @returns {boolean}
	 */
	function isReact19Plus() {
	    // React 19 is detected by checking React version if available
	    // In practice, we'll use a more conservative approach and assume React 18 behavior
	    // unless we can definitively detect React 19
	    try {
	        // @ts-ignore
	        if (React.version) {
	            const majorVersion = parseInt(React.version.split('.')[0], 10);
	            return majorVersion >= 19;
	        }
	    }
	    catch {
	        // Fallback to React 18 behavior if we can't determine version
	    }
	    return false;
	}
	/**
	 * The ReactRenderer class. It's responsible for rendering React components inside the editor.
	 * @example
	 * new ReactRenderer(MyComponent, {
	 *   editor,
	 *   props: {
	 *     foo: 'bar',
	 *   },
	 *   as: 'span',
	 * })
	*/
	class ReactRenderer {
	    /**
	     * Immediately creates element and renders the provided React component.
	     */
	    constructor(component, { editor, props = {}, as = 'div', className = '', }) {
	        this.ref = null;
	        this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString();
	        this.component = component;
	        this.editor = editor;
	        this.props = props;
	        this.element = document.createElement(as);
	        this.element.classList.add('react-renderer');
	        if (className) {
	            this.element.classList.add(...className.split(' '));
	        }
	        // If the editor is already initialized, we will need to
	        // synchronously render the component to ensure it renders
	        // together with Prosemirror's rendering.
	        if (this.editor.isInitialized) {
	            ReactDOM.flushSync(() => {
	                this.render();
	            });
	        }
	        else {
	            queueMicrotask(() => {
	                this.render();
	            });
	        }
	    }
	    /**
	     * Render the React component.
	     */
	    render() {
	        var _a;
	        const Component = this.component;
	        const props = this.props;
	        const editor = this.editor;
	        // Handle ref forwarding with React 18/19 compatibility
	        const isReact19 = isReact19Plus();
	        const componentCanReceiveRef = canReceiveRef(Component);
	        const elementProps = { ...props };
	        // Always remove ref if the component cannot receive it (unless React 19+)
	        if (elementProps.ref && !(isReact19 || componentCanReceiveRef)) {
	            delete elementProps.ref;
	        }
	        // Only assign our own ref if allowed
	        if (!elementProps.ref && (isReact19 || componentCanReceiveRef)) {
	            // @ts-ignore - Setting ref prop for compatible components
	            elementProps.ref = (ref) => {
	                this.ref = ref;
	            };
	        }
	        this.reactElement = React.createElement(Component, { ...elementProps });
	        (_a = editor === null || editor === void 0 ? void 0 : editor.contentComponent) === null || _a === void 0 ? void 0 : _a.setRenderer(this.id, this);
	    }
	    /**
	     * Re-renders the React component with new props.
	     */
	    updateProps(props = {}) {
	        this.props = {
	            ...this.props,
	            ...props,
	        };
	        this.render();
	    }
	    /**
	     * Destroy the React component.
	     */
	    destroy() {
	        var _a;
	        const editor = this.editor;
	        (_a = editor === null || editor === void 0 ? void 0 : editor.contentComponent) === null || _a === void 0 ? void 0 : _a.removeRenderer(this.id);
	    }
	    /**
	     * Update the attributes of the element that holds the React component.
	     */
	    updateAttributes(attributes) {
	        Object.keys(attributes).forEach(key => {
	            this.element.setAttribute(key, attributes[key]);
	        });
	    }
	}

	class ReactNodeView extends core.NodeView {
	    constructor(component, props, options) {
	        super(component, props, options);
	        if (!this.node.isLeaf) {
	            if (this.options.contentDOMElementTag) {
	                this.contentDOMElement = document.createElement(this.options.contentDOMElementTag);
	            }
	            else {
	                this.contentDOMElement = document.createElement(this.node.isInline ? 'span' : 'div');
	            }
	            this.contentDOMElement.dataset.nodeViewContentReact = '';
	            this.contentDOMElement.dataset.nodeViewWrapper = '';
	            // For some reason the whiteSpace prop is not inherited properly in Chrome and Safari
	            // With this fix it seems to work fine
	            // See: https://github.com/ueberdosis/tiptap/issues/1197
	            this.contentDOMElement.style.whiteSpace = 'inherit';
	            const contentTarget = this.dom.querySelector('[data-node-view-content]');
	            if (!contentTarget) {
	                return;
	            }
	            contentTarget.appendChild(this.contentDOMElement);
	        }
	    }
	    /**
	     * Setup the React component.
	     * Called on initialization.
	     */
	    mount() {
	        const props = {
	            editor: this.editor,
	            node: this.node,
	            decorations: this.decorations,
	            innerDecorations: this.innerDecorations,
	            view: this.view,
	            selected: false,
	            extension: this.extension,
	            HTMLAttributes: this.HTMLAttributes,
	            getPos: () => this.getPos(),
	            updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
	            deleteNode: () => this.deleteNode(),
	            ref: React.createRef(),
	        };
	        if (!this.component.displayName) {
	            const capitalizeFirstChar = (string) => {
	                return string.charAt(0).toUpperCase() + string.substring(1);
	            };
	            this.component.displayName = capitalizeFirstChar(this.extension.name);
	        }
	        const onDragStart = this.onDragStart.bind(this);
	        const nodeViewContentRef = element => {
	            if (element && this.contentDOMElement && element.firstChild !== this.contentDOMElement) {
	                // remove the nodeViewWrapper attribute from the element
	                if (element.hasAttribute('data-node-view-wrapper')) {
	                    element.removeAttribute('data-node-view-wrapper');
	                }
	                element.appendChild(this.contentDOMElement);
	            }
	        };
	        const context = { onDragStart, nodeViewContentRef };
	        const Component = this.component;
	        // For performance reasons, we memoize the provider component
	        // And all of the things it requires are declared outside of the component, so it doesn't need to re-render
	        const ReactNodeViewProvider = React.memo(componentProps => {
	            return (React.createElement(ReactNodeViewContext.Provider, { value: context }, React.createElement(Component, componentProps)));
	        });
	        ReactNodeViewProvider.displayName = 'ReactNodeView';
	        let as = this.node.isInline ? 'span' : 'div';
	        if (this.options.as) {
	            as = this.options.as;
	        }
	        const { className = '' } = this.options;
	        this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
	        this.renderer = new ReactRenderer(ReactNodeViewProvider, {
	            editor: this.editor,
	            props,
	            as,
	            className: `node-${this.node.type.name} ${className}`.trim(),
	        });
	        this.editor.on('selectionUpdate', this.handleSelectionUpdate);
	        this.updateElementAttributes();
	    }
	    /**
	     * Return the DOM element.
	     * This is the element that will be used to display the node view.
	     */
	    get dom() {
	        var _a;
	        if (this.renderer.element.firstElementChild
	            && !((_a = this.renderer.element.firstElementChild) === null || _a === void 0 ? void 0 : _a.hasAttribute('data-node-view-wrapper'))) {
	            throw Error('Please use the NodeViewWrapper component for your node view.');
	        }
	        return this.renderer.element;
	    }
	    /**
	     * Return the content DOM element.
	     * This is the element that will be used to display the rich-text content of the node.
	     */
	    get contentDOM() {
	        if (this.node.isLeaf) {
	            return null;
	        }
	        return this.contentDOMElement;
	    }
	    /**
	     * On editor selection update, check if the node is selected.
	     * If it is, call `selectNode`, otherwise call `deselectNode`.
	     */
	    handleSelectionUpdate() {
	        const { from, to } = this.editor.state.selection;
	        const pos = this.getPos();
	        if (typeof pos !== 'number') {
	            return;
	        }
	        if (from <= pos && to >= pos + this.node.nodeSize) {
	            if (this.renderer.props.selected) {
	                return;
	            }
	            this.selectNode();
	        }
	        else {
	            if (!this.renderer.props.selected) {
	                return;
	            }
	            this.deselectNode();
	        }
	    }
	    /**
	     * On update, update the React component.
	     * To prevent unnecessary updates, the `update` option can be used.
	     */
	    update(node, decorations, innerDecorations) {
	        const rerenderComponent = (props) => {
	            this.renderer.updateProps(props);
	            if (typeof this.options.attrs === 'function') {
	                this.updateElementAttributes();
	            }
	        };
	        if (node.type !== this.node.type) {
	            return false;
	        }
	        if (typeof this.options.update === 'function') {
	            const oldNode = this.node;
	            const oldDecorations = this.decorations;
	            const oldInnerDecorations = this.innerDecorations;
	            this.node = node;
	            this.decorations = decorations;
	            this.innerDecorations = innerDecorations;
	            return this.options.update({
	                oldNode,
	                oldDecorations,
	                newNode: node,
	                newDecorations: decorations,
	                oldInnerDecorations,
	                innerDecorations,
	                updateProps: () => rerenderComponent({ node, decorations, innerDecorations }),
	            });
	        }
	        if (node === this.node
	            && this.decorations === decorations
	            && this.innerDecorations === innerDecorations) {
	            return true;
	        }
	        this.node = node;
	        this.decorations = decorations;
	        this.innerDecorations = innerDecorations;
	        rerenderComponent({ node, decorations, innerDecorations });
	        return true;
	    }
	    /**
	     * Select the node.
	     * Add the `selected` prop and the `ProseMirror-selectednode` class.
	     */
	    selectNode() {
	        this.renderer.updateProps({
	            selected: true,
	        });
	        this.renderer.element.classList.add('ProseMirror-selectednode');
	    }
	    /**
	     * Deselect the node.
	     * Remove the `selected` prop and the `ProseMirror-selectednode` class.
	     */
	    deselectNode() {
	        this.renderer.updateProps({
	            selected: false,
	        });
	        this.renderer.element.classList.remove('ProseMirror-selectednode');
	    }
	    /**
	     * Destroy the React component instance.
	     */
	    destroy() {
	        this.renderer.destroy();
	        this.editor.off('selectionUpdate', this.handleSelectionUpdate);
	        this.contentDOMElement = null;
	    }
	    /**
	     * Update the attributes of the top-level element that holds the React component.
	     * Applying the attributes defined in the `attrs` option.
	     */
	    updateElementAttributes() {
	        if (this.options.attrs) {
	            let attrsObj = {};
	            if (typeof this.options.attrs === 'function') {
	                const extensionAttributes = this.editor.extensionManager.attributes;
	                const HTMLAttributes = core.getRenderedAttributes(this.node, extensionAttributes);
	                attrsObj = this.options.attrs({ node: this.node, HTMLAttributes });
	            }
	            else {
	                attrsObj = this.options.attrs;
	            }
	            this.renderer.updateAttributes(attrsObj);
	        }
	    }
	}
	/**
	 * Create a React node view renderer.
	 */
	function ReactNodeViewRenderer(component, options) {
	    return props => {
	        // try to get the parent component
	        // this is important for vue devtools to show the component hierarchy correctly
	        // maybe it’s `undefined` because <editor-content> isn’t rendered yet
	        if (!props.editor.contentComponent) {
	            return {};
	        }
	        return new ReactNodeView(component, props, options);
	    };
	}

	exports.BubbleMenu = BubbleMenu;
	exports.EditorConsumer = EditorConsumer;
	exports.EditorContent = EditorContent;
	exports.EditorContext = EditorContext;
	exports.EditorProvider = EditorProvider;
	exports.FloatingMenu = FloatingMenu;
	exports.NodeViewContent = NodeViewContent;
	exports.NodeViewWrapper = NodeViewWrapper;
	exports.PureEditorContent = PureEditorContent;
	exports.ReactNodeView = ReactNodeView;
	exports.ReactNodeViewContext = ReactNodeViewContext;
	exports.ReactNodeViewRenderer = ReactNodeViewRenderer;
	exports.ReactRenderer = ReactRenderer;
	exports.useCurrentEditor = useCurrentEditor;
	exports.useEditor = useEditor;
	exports.useEditorState = useEditorState;
	exports.useReactNodeView = useReactNodeView;
	Object.keys(core).forEach(function (k) {
		if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
			enumerable: true,
			get: function () { return core[k]; }
		});
	});

}));
//# sourceMappingURL=index.umd.js.map
