/*!
 * Jodit Editor (https://xdsoft.net/jodit/)
 * Released under MIT see LICENSE.txt in the project root for license information.
 * Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
 */
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
        r = Reflect.decorate(decorators, target, key, desc);
    else
        for (var i = decorators.length - 1; i >= 0; i--)
            if (d = decorators[i])
                r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { autobind, cache, debounce, wait, watch } from "../../core/decorators/index.js";
import { Dom } from "../../core/dom/index.js";
import { pluginSystem } from "../../core/global.js";
import { camelCase, isArray, isFunction, isString, keys, position, splitArray, toArray } from "../../core/helpers/index.js";
import { Plugin } from "../../core/plugin/index.js";
import { UIElement } from "../../core/ui/index.js";
import { Popup } from "../../core/ui/popup/index.js";
import { makeCollection } from "../../modules/toolbar/factory.js";
import "./config/config.js";
/**
 * Plugin for show inline popup dialog
 */
export class inlinePopup extends Plugin {
    constructor() {
        super(...arguments);
        this.type = null;
        this.snapRange = null;
        this.elmsList = keys(this.j.o.popup, false).filter(s => !this.isExcludedTarget(s));
    }
    get popup() {
        return new Popup(this.jodit, false);
    }
    get toolbar() {
        return makeCollection(this.jodit, this.popup);
    }
    onClick(node) {
        const elements = this.elmsList, target = Dom.isTag(node, 'img')
            ? node
            : Dom.closest(node, elements, this.j.editor);
        if (target && this.canShowPopupForType(target.nodeName.toLowerCase())) {
            this.showPopup(() => position(target, this.j), target.nodeName.toLowerCase(), target);
            return false;
        }
    }
    /**
     * Show inline popup with some toolbar
     *
     * @param type - selection, img, a etc.
     */
    showPopup(rect, type, target) {
        type = type.toLowerCase();
        if (!this.canShowPopupForType(type)) {
            return false;
        }
        if (this.type !== type || target !== this.previousTarget) {
            this.previousTarget = target;
            const data = this.j.o.popup[type];
            let content;
            if (isFunction(data)) {
                content = data(this.j, target, this.popup.close);
            }
            else {
                content = data;
            }
            if (isArray(content)) {
                this.toolbar.build(content, target);
                this.toolbar.buttonSize = this.j.o.toolbarButtonSize;
                content = this.toolbar.container;
            }
            this.popup.setContent(content);
            this.type = type;
        }
        this.popup.open(rect);
        return true;
    }
    /**
     * Hide opened popup
     */
    hidePopup(type) {
        if (this.popup.isOpened && (!isString(type) || type === this.type)) {
            this.popup.close();
        }
    }
    onOutsideClick() {
        this.popup.close();
    }
    /**
     * Can show popup for this type
     */
    canShowPopupForType(type) {
        const data = this.j.o.popup[type.toLowerCase()];
        if (this.j.o.readonly || !this.j.o.toolbarInline || !data) {
            return false;
        }
        return !this.isExcludedTarget(type);
    }
    /**
     * For some elements do not show popup
     */
    isExcludedTarget(type) {
        return splitArray(this.j.o.toolbarInlineDisableFor)
            .map(a => a.toLowerCase())
            .includes(type.toLowerCase());
    }
    /** @override **/
    afterInit(jodit) {
        this.j.e
            .on('getDiffButtons.mobile', (toolbar) => {
            if (this.toolbar === toolbar) {
                const names = this.toolbar.getButtonsNames();
                return toArray(jodit.registeredButtons)
                    .filter(btn => !this.j.o.toolbarInlineDisabledButtons.includes(btn.name))
                    .filter(item => {
                    const name = isString(item) ? item : item.name;
                    return (name &&
                        name !== '|' &&
                        name !== '\n' &&
                        !names.includes(name));
                });
            }
        })
            .on('hidePopup', this.hidePopup)
            .on('showInlineToolbar', this.showInlineToolbar)
            .on('showPopup', (elm, rect, type) => {
            this.showPopup(rect, type || (isString(elm) ? elm : elm.nodeName), isString(elm) ? undefined : elm);
        })
            .on('mousedown keydown', this.onSelectionStart)
            .on('change', () => {
            if (this.popup.isOpened &&
                this.previousTarget &&
                !this.previousTarget.parentNode) {
                this.hidePopup();
                this.previousTarget = undefined;
            }
        })
            .on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
        this.addListenersForElements();
    }
    onSelectionStart() {
        this.snapRange = this.j.s.range.cloneRange();
    }
    onSelectionEnd(e) {
        if (e &&
            e.target &&
            UIElement.closestElement(e.target, Popup)) {
            return;
        }
        const { snapRange } = this, { range } = this.j.s;
        if (!snapRange ||
            range.collapsed ||
            range.startContainer !== snapRange.startContainer ||
            range.startOffset !== snapRange.startOffset ||
            range.endContainer !== snapRange.endContainer ||
            range.endOffset !== snapRange.endOffset) {
            this.onSelectionChange();
        }
    }
    /**
     * Selection change handler
     */
    onSelectionChange() {
        if (!this.j.o.toolbarInlineForSelection) {
            return;
        }
        const type = 'selection';
        const sel = this.j.s.sel;
        const range = this.j.s.range;
        if ((sel === null || sel === void 0 ? void 0 : sel.isCollapsed) || this.isSelectedTarget(range)) {
            if (this.type === type && this.popup.isOpened) {
                this.hidePopup();
            }
            return;
        }
        const node = this.j.s.current();
        if (!node) {
            return;
        }
        this.showPopup(() => range.getBoundingClientRect(), type);
    }
    /**
     * In not collapsed selection - only one image
     */
    isSelectedTarget(r) {
        const sc = r.startContainer;
        return (Dom.isElement(sc) &&
            sc === r.endContainer &&
            Dom.isTag(sc.childNodes[r.startOffset], new Set(keys(this.j.o.popup, false))) &&
            r.startOffset === r.endOffset - 1);
    }
    /**
     * Shortcut for Table module
     */
    // private get tableModule(): Table {
    // 	return this.j.getInstance<Table>('Table', this.j.o);
    // }
    /** @override **/
    beforeDestruct(jodit) {
        jodit.e
            .off('showPopup')
            .off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
        this.removeListenersForElements();
    }
    _eventsList() {
        const el = this.elmsList;
        return el
            .map(e => camelCase(`click_${e}`))
            .concat(el.map(e => camelCase(`touchstart_${e}`)))
            .join(' ');
    }
    addListenersForElements() {
        this.j.e.on(this._eventsList(), this.onClick);
    }
    removeListenersForElements() {
        this.j.e.off(this._eventsList(), this.onClick);
    }
    /**
     * Show the inline WYSIWYG toolbar editor.
     */
    showInlineToolbar(bound) {
        this.showPopup(() => {
            if (bound) {
                return bound;
            }
            const { range } = this.j.s;
            return range.getBoundingClientRect();
        }, 'toolbar');
    }
}
inlinePopup.requires = ['select'];
__decorate([
    cache
], inlinePopup.prototype, "popup", null);
__decorate([
    cache
], inlinePopup.prototype, "toolbar", null);
__decorate([
    autobind
], inlinePopup.prototype, "onClick", null);
__decorate([
    wait((ctx) => !ctx.j.isLocked)
], inlinePopup.prototype, "showPopup", null);
__decorate([
    watch([':clickEditor', ':beforeCommandDelete', ':backSpaceAfterDelete']),
    autobind
], inlinePopup.prototype, "hidePopup", null);
__decorate([
    watch(':outsideClick')
], inlinePopup.prototype, "onOutsideClick", null);
__decorate([
    autobind
], inlinePopup.prototype, "onSelectionStart", null);
__decorate([
    autobind
], inlinePopup.prototype, "onSelectionEnd", null);
__decorate([
    debounce(ctx => ctx.defaultTimeout)
], inlinePopup.prototype, "onSelectionChange", null);
__decorate([
    autobind
], inlinePopup.prototype, "showInlineToolbar", null);
pluginSystem.add('inlinePopup', inlinePopup);
