'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var core = require('@tiptap/core'); var state = require('@tiptap/pm/state'); var tippy = require('tippy.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var tippy__default = /*#__PURE__*/_interopDefaultLegacy(tippy); class FloatingMenuView { constructor({ editor, element, view, tippyOptions = {}, shouldShow, }) { this.preventHide = false; this.shouldShow = ({ view, state }) => { const { selection } = state; const { $anchor, empty } = selection; const isRootDepth = $anchor.depth === 1; const isEmptyTextBlock = $anchor.parent.isTextblock && !$anchor.parent.type.spec.code && !$anchor.parent.textContent; if (!view.hasFocus() || !empty || !isRootDepth || !isEmptyTextBlock || !this.editor.isEditable) { return false; } return true; }; this.mousedownHandler = () => { this.preventHide = true; }; this.focusHandler = () => { // we use `setTimeout` to make sure `selection` is already updated setTimeout(() => this.update(this.editor.view)); }; this.blurHandler = ({ event }) => { var _a; if (this.preventHide) { this.preventHide = false; return; } if ((event === null || event === void 0 ? void 0 : event.relatedTarget) && ((_a = this.element.parentNode) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget))) { return; } this.hide(); }; this.tippyBlurHandler = (event) => { this.blurHandler({ event }); }; this.editor = editor; this.element = element; this.view = view; if (shouldShow) { this.shouldShow = shouldShow; } this.element.addEventListener('mousedown', this.mousedownHandler, { capture: true }); this.editor.on('focus', this.focusHandler); this.editor.on('blur', this.blurHandler); this.tippyOptions = tippyOptions; // Detaches menu content from its current parent this.element.remove(); this.element.style.visibility = 'visible'; } createTooltip() { const { element: editorElement } = this.editor.options; const editorIsAttached = !!editorElement.parentElement; if (this.tippy || !editorIsAttached) { return; } this.tippy = tippy__default["default"](editorElement, { duration: 0, getReferenceClientRect: null, content: this.element, interactive: true, trigger: 'manual', placement: 'right', hideOnClick: 'toggle', ...this.tippyOptions, }); // maybe we have to hide tippy on its own blur event as well if (this.tippy.popper.firstChild) { this.tippy.popper.firstChild.addEventListener('blur', this.tippyBlurHandler); } } update(view, oldState) { var _a, _b, _c; const { state } = view; const { doc, selection } = state; const { from, to } = selection; const isSame = oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection); if (isSame) { return; } this.createTooltip(); const shouldShow = (_a = this.shouldShow) === null || _a === void 0 ? void 0 : _a.call(this, { editor: this.editor, view, state, oldState, }); if (!shouldShow) { this.hide(); return; } (_b = this.tippy) === null || _b === void 0 ? void 0 : _b.setProps({ getReferenceClientRect: ((_c = this.tippyOptions) === null || _c === void 0 ? void 0 : _c.getReferenceClientRect) || (() => core.posToDOMRect(view, from, to)), }); this.show(); } show() { var _a; (_a = this.tippy) === null || _a === void 0 ? void 0 : _a.show(); } hide() { var _a; (_a = this.tippy) === null || _a === void 0 ? void 0 : _a.hide(); } destroy() { var _a, _b; if ((_a = this.tippy) === null || _a === void 0 ? void 0 : _a.popper.firstChild) { this.tippy.popper.firstChild.removeEventListener('blur', this.tippyBlurHandler); } (_b = this.tippy) === null || _b === void 0 ? void 0 : _b.destroy(); this.element.removeEventListener('mousedown', this.mousedownHandler, { capture: true }); this.editor.off('focus', this.focusHandler); this.editor.off('blur', this.blurHandler); } } const FloatingMenuPlugin = (options) => { return new state.Plugin({ key: typeof options.pluginKey === 'string' ? new state.PluginKey(options.pluginKey) : options.pluginKey, view: view => new FloatingMenuView({ view, ...options }), }); }; const FloatingMenu = core.Extension.create({ name: 'floatingMenu', addOptions() { return { element: null, tippyOptions: {}, pluginKey: 'floatingMenu', shouldShow: null, }; }, addProseMirrorPlugins() { if (!this.options.element) { return []; } return [ FloatingMenuPlugin({ pluginKey: this.options.pluginKey, editor: this.editor, element: this.options.element, tippyOptions: this.options.tippyOptions, shouldShow: this.options.shouldShow, }), ]; }, }); exports.FloatingMenu = FloatingMenu; exports.FloatingMenuPlugin = FloatingMenuPlugin; exports.FloatingMenuView = FloatingMenuView; exports["default"] = FloatingMenu; //# sourceMappingURL=index.cjs.map