/**
 * amis-ui v6.12.0-beta.0
 * Copyright 2018-2025 fex
 */

import { __extends, __awaiter, __generator, __decorate, __metadata } from 'tslib';
import { calculatePosition, autobind, themeable } from 'amis-core';
import React__default from 'react';
import { render } from 'react-dom';
import Transition, { ENTERING, ENTERED, EXITING } from 'react-transition-group/Transition';
import debounce from 'lodash/debounce';

var _a;
// import {createRoot} from 'react-dom/client';
var fadeStyles = (_a = {},
    _a[ENTERING] = 'in',
    _a[ENTERED] = 'in',
    _a[EXITING] = 'out',
    _a);
var ContextMenu = /** @class */ (function (_super) {
    __extends(ContextMenu, _super);
    function ContextMenu(props) {
        var _this = _super.call(this, props) || this;
        _this.state = {
            isOpened: false,
            menus: [],
            x: -99999,
            y: -99999,
            cursorX: -99999,
            cursorY: -99999
        };
        _this.menuRef = React__default.createRef();
        _this.contentRef = React__default.createRef();
        _this.unmount = false;
        _this.menuEntered = false;
        _this.resizeObserver = null;
        _this.originInstance = ContextMenu.instance;
        ContextMenu.instance = _this;
        _this.debounceCalculatePosition = debounce(_this.autoCalculatePosition.bind(_this), 200);
        return _this;
    }
    ContextMenu.getInstance = function () {
        return __awaiter(this, void 0, void 0, function () {
            var container, div;
            return __generator(this, function (_a) {
                if (!ContextMenu.instance || ContextMenu.instance.unmount) {
                    container = document.body;
                    div = document.createElement('div');
                    container.appendChild(div);
                    // if (parseInt(version.split('.')[0], 10) >= 18) {
                    //   const root = createRoot(div);
                    //   await new Promise<void>(resolve =>
                    //     root.render(<ThemedContextMenu ref={() => resolve()} />)
                    //   );
                    // } else {
                    render(React__default.createElement(ThemedContextMenu, null), div);
                    // }
                }
                return [2 /*return*/, ContextMenu.instance];
            });
        });
    };
    ContextMenu.prototype.componentDidMount = function () {
        document.body.addEventListener('click', this.handleOutClick, true);
        document.addEventListener('keydown', this.handleKeyDown);
    };
    ContextMenu.prototype.componentWillUnmount = function () {
        this.unmount = true;
        this.debounceCalculatePosition.cancel();
        ContextMenu.instance = this.originInstance;
        document.body.removeEventListener('click', this.handleOutClick, true);
        document.removeEventListener('keydown', this.handleKeyDown);
        // @ts-ignore
        delete this.originInstance;
    };
    ContextMenu.prototype.openContextMenus = function (info, menus, onClose, options) {
        var _this = this;
        if (this.state.isOpened) {
            var _a = this.state, x = _a.x, y = _a.y;
            var cursorX = x + (info.x - (this.prevInfo && this.prevInfo.x ? this.prevInfo.x : 0));
            var cursorY = y + (info.y - (this.prevInfo && this.prevInfo.y ? this.prevInfo.y : 0));
            // 避免 二次触发未进行智能定位 导致遮挡问题
            this.setState({
                x: cursorX,
                y: cursorY,
                cursorX: cursorX,
                cursorY: cursorY,
                menus: menus,
                onClose: onClose,
                contentClassName: options === null || options === void 0 ? void 0 : options.contentClassName,
                preventClose: options === null || options === void 0 ? void 0 : options.preventClose
            }, function () {
                _this.handleEnter(_this.menuRef.current);
            });
        }
        else {
            this.setState({
                isOpened: true,
                x: info.x,
                y: info.y,
                cursorX: info.x,
                cursorY: info.y,
                menus: menus,
                onClose: onClose,
                contentClassName: options === null || options === void 0 ? void 0 : options.contentClassName,
                preventClose: options === null || options === void 0 ? void 0 : options.preventClose
            });
        }
        this.prevInfo = info;
    };
    ContextMenu.prototype.close = function (e) {
        var _this = this;
        var _a, _b, _c, _d;
        if ((_b = (_a = this.state).preventClose) === null || _b === void 0 ? void 0 : _b.call(_a, e)) {
            return;
        }
        (_c = e === null || e === void 0 ? void 0 : e.preventDefault) === null || _c === void 0 ? void 0 : _c.call(e);
        this.menuEntered = false;
        (_d = this.resizeObserver) === null || _d === void 0 ? void 0 : _d.disconnect();
        var onClose = this.state.onClose;
        this.setState({
            isOpened: false,
            x: -99999,
            y: -99999,
            cursorX: -99999,
            cursorY: -99999,
            menus: [],
            contentClassName: '',
            preventClose: undefined
        }, function () {
            onClose === null || onClose === void 0 ? void 0 : onClose(_this);
        });
    };
    ContextMenu.prototype.handleOutClick = function (e) {
        if (!this.menuEntered ||
            !e.target ||
            !this.menuRef.current ||
            this.menuRef.current.contains(e.target)) {
            return;
        }
        if (this.state.isOpened) {
            this.close(e);
        }
    };
    ContextMenu.prototype.handleClick = function (item) {
        var _this = this;
        var onClose = this.state.onClose;
        item.disabled ||
            (Array.isArray(item.children) && item.children.length) ||
            this.setState({
                isOpened: false,
                x: -99999,
                y: -99999,
                cursorX: -99999,
                cursorY: -99999,
                menus: []
            }, function () {
                var _a;
                (_a = item.onSelect) === null || _a === void 0 ? void 0 : _a.call(item, item.data);
                onClose === null || onClose === void 0 ? void 0 : onClose(_this);
            });
    };
    ContextMenu.prototype.handleKeyDown = function (e) {
        if (e.keyCode === 27 && this.state.isOpened) {
            this.close(e);
        }
    };
    ContextMenu.prototype.handleMouseEnter = function (item) {
        item.disabled || !item.onHighlight || item.onHighlight(true, item.data);
    };
    ContextMenu.prototype.handleMouseLeave = function (item) {
        item.disabled || !item.onHighlight || item.onHighlight(false, item.data);
    };
    ContextMenu.prototype.handleEnter = function (menu) {
        this.autoCalculatePosition(menu);
    };
    ContextMenu.prototype.handleEntered = function (menu) {
        var _this = this;
        this.menuEntered = true;
        if (!this.contentRef.current || !window.ResizeObserver) {
            return;
        }
        // 监听菜单大小变化，并自动重新计算位置
        this.resizeObserver = new ResizeObserver(function (entries) {
            entries.length && _this.debounceCalculatePosition(menu);
        });
        this.resizeObserver.observe(this.contentRef.current);
    };
    ContextMenu.prototype.autoCalculatePosition = function (menu) {
        // 智能定位，选择一个合适的对齐方式。
        var info = calculatePosition('asContextMenu', menu.lastChild, menu.children[1], menu.children[0]);
        var align = info.positionLeft + 300 < window.innerWidth ? 'right' : 'left';
        this.setState({
            x: info.positionLeft,
            y: info.positionTop,
            align: align
        });
    };
    ContextMenu.prototype.handleSelfContextMenu = function (e) {
        e.preventDefault();
    };
    ContextMenu.prototype.renderMenus = function (menus) {
        var _this = this;
        var cx = this.props.classnames;
        return menus.map(function (item, index) {
            if (item === '|') {
                return React__default.createElement("li", { key: index, className: cx('ContextMenu-divider') });
            }
            var hasChildren = Array.isArray(item.children) && item.children.length;
            return (React__default.createElement("li", { key: "".concat(item.label, "-").concat(index), className: cx('ContextMenu-item', item.className, {
                    'has-child': hasChildren,
                    'is-disabled': item.disabled,
                    'is-active': item.selected
                }) },
                React__default.createElement("a", { onClick: _this.handleClick.bind(_this, item), onMouseEnter: _this.handleMouseEnter.bind(_this, item), onMouseLeave: _this.handleMouseLeave.bind(_this, item) },
                    item.icon ? (React__default.createElement("span", { className: cx('ContextMenu-itemIcon', item.icon) })) : null,
                    item.label,
                    hasChildren ? React__default.createElement("i", { className: "fas fa-chevron-right" }) : null,
                    item.selected ? React__default.createElement("i", { className: "fas fa-check" }) : null),
                hasChildren ? (React__default.createElement("ul", { className: cx('ContextMenu-subList') }, _this.renderMenus(item.children))) : null));
        });
    };
    ContextMenu.prototype.render = function () {
        var _this = this;
        var _a = this.props, className = _a.className; _a.container; var cx = _a.classnames;
        return (React__default.createElement(Transition, { mountOnEnter: true, unmountOnExit: true, onEnter: this.handleEnter, in: this.state.isOpened, timeout: 500, onEntered: this.handleEntered }, function (status) { return (React__default.createElement("div", { ref: _this.menuRef, role: "contextmenu", className: cx('ContextMenu', {
                'ContextMenu--left': _this.state.align === 'left'
            }, className, _this.state.contentClassName), onContextMenu: _this.handleSelfContextMenu },
            React__default.createElement("div", { className: cx("ContextMenu-overlay", fadeStyles[status]) }),
            React__default.createElement("div", { className: cx("ContextMenu-cursor"), style: {
                    left: "".concat(_this.state.cursorX, "px"),
                    top: "".concat(_this.state.cursorY, "px")
                } }),
            React__default.createElement("div", { ref: _this.contentRef, style: { left: "".concat(_this.state.x, "px"), top: "".concat(_this.state.y, "px") }, className: cx("ContextMenu-menu", fadeStyles[status]) }, typeof _this.state.menus === 'function' ? (_this.state.menus()) : (React__default.createElement("ul", { className: cx('ContextMenu-list') }, _this.renderMenus(_this.state.menus)))))); }));
    };
    ContextMenu.instance = null;
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object, Array, Function, Object]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "openContextMenus", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Event]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "close", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Event]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "handleOutClick", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [KeyboardEvent]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "handleKeyDown", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [HTMLElement]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "handleEnter", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [HTMLElement]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "handleEntered", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [HTMLElement]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "autoCalculatePosition", null);
    __decorate([
        autobind,
        __metadata("design:type", Function),
        __metadata("design:paramtypes", [Object]),
        __metadata("design:returntype", void 0)
    ], ContextMenu.prototype, "handleSelfContextMenu", null);
    return ContextMenu;
}(React__default.Component));
var ThemedContextMenu = themeable(ContextMenu);
function openContextMenus(info, menus, onClose, options) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            return [2 /*return*/, ContextMenu.getInstance().then(function (instance) {
                    return instance.openContextMenus(info, menus, onClose, options);
                })];
        });
    });
}
function closeContextMenus() {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            return [2 /*return*/, ContextMenu.getInstance().then(function (instance) { return instance === null || instance === void 0 ? void 0 : instance.close(); })];
        });
    });
}

export { ContextMenu, ThemedContextMenu, closeContextMenus, ThemedContextMenu as default, openContextMenus };
