import { keydownHandler } from 'prosemirror-keymap';
import { AllSelection, Plugin, TextSelection, } from 'prosemirror-state';
import { isCodeBlock } from "../../../utils/nodes.js";
import { TooltipView } from "./tooltip.js";
export const SelectionContext = (builder, { config }) => {
    if (Array.isArray(config) && config.length > 0) {
        builder.addPlugin(({ actions }) => new Plugin(new SelectionTooltip(actions, config, builder.logger)));
    }
};
class SelectionTooltip {
    destroyed = false;
    tooltip;
    hideTimeoutRef = null;
    _isMousePressed = false;
    constructor(actions, menuConfig, logger) {
        this.tooltip = new TooltipView(actions, menuConfig, logger);
    }
    get props() {
        return {
            // same as keymap({})
            handleKeyDown: keydownHandler({
                // hide context menu when Esc was pressed
                Escape: (_state, _dispatch, view) => {
                    if (this.tooltip.isTooltipOpen) {
                        this.tooltip.hide(view);
                        return true;
                    }
                    return false;
                },
            }),
            handleDOMEvents: {
                mousedown: (view) => {
                    const startState = {
                        doc: view.state.doc,
                        selection: view.state.selection,
                    };
                    this._isMousePressed = true;
                    this.cancelTooltipHiding();
                    this.tooltip.hide(view);
                    const onMouseUp = () => {
                        if (this.destroyed)
                            return;
                        this._isMousePressed = false;
                        this.update(view, startState);
                    };
                    document.addEventListener('mouseup', onMouseUp, { once: true });
                },
            },
        };
    }
    view(view) {
        this.update(view);
        return {
            update: this.update.bind(this),
            destroy: () => {
                this.destroyed = true;
                this.cancelTooltipHiding();
                this.tooltip.destroy();
            },
        };
    }
    update(view, prevState) {
        if (this._isMousePressed)
            return;
        this.cancelTooltipHiding();
        // Don't show tooltip if editor not mounted to the DOM
        // or when view is out of focus
        if (!view.dom.parentNode || !view.hasFocus()) {
            this.tooltip.hide(view);
            return;
        }
        const { state } = view;
        // Don't do anything if the document/selection didn't change
        if (prevState && prevState.doc.eq(state.doc) && prevState.selection.eq(state.selection))
            return;
        const { selection } = state;
        // Hide the tooltip if the selection is empty
        if (selection.empty ||
            !(selection instanceof TextSelection || selection instanceof AllSelection)) {
            this.tooltip.hide(view);
            return;
        }
        // Hide the tooltip when one side of selection inside codeblock
        if (isCodeBlock(selection.$from.parent) || isCodeBlock(selection.$to.parent)) {
            this.tooltip.hide(view);
            return;
        }
        this.tooltip.show(view, {
            onOpenChange: (_open, _event, reason) => {
                if (reason !== 'escape-key')
                    this.scheduleTooltipHiding(view);
            },
        });
    }
    scheduleTooltipHiding(view) {
        this.hideTimeoutRef = setTimeout(() => {
            // hide tooltip if view is out of focus after 30 ms
            if (!view.hasFocus()) {
                this.tooltip.hide(view);
            }
        }, 30);
    }
    cancelTooltipHiding() {
        if (this.hideTimeoutRef !== null) {
            clearTimeout(this.hideTimeoutRef);
            this.hideTimeoutRef = null;
        }
    }
}
//# sourceMappingURL=index.js.map
