"use strict";
/*
 * Copyright 2023 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.hideContextMenu = exports.showContextMenu = void 0;
var tslib_1 = require("tslib");
var React = tslib_1.__importStar(require("react"));
var ReactDOM = tslib_1.__importStar(require("react-dom"));
var common_1 = require("../../common");
var overlaysProvider_1 = require("../../context/overlays/overlaysProvider");
var contextMenuPopover_1 = require("./contextMenuPopover");
/** State which contains the context menu singleton instance for the imperative ContextMenu APIs. */
var contextMenuState;
/**
 * Show a context menu at a particular offset from the top-left corner of the document.
 * The menu will appear below-right of this point and will flip to below-left if there is not enough
 * room onscreen. Additional props like `onClose`, `isDarkTheme`, etc. can be forwarded to the `<ContextMenuPopover>`.
 *
 * Context menus created with this API will automatically close when a user clicks outside the popover.
 * You may force them to close by using `hideContextMenu()`.
 *
 * Note that this API relies on global state in the @blueprintjs/core package, and should be used with caution,
 * especially if your build system allows multiple copies of Blueprint libraries to be bundled into an application at
 * once.
 *
 * Alternative APIs to consider which do not have the limitations of global state:
 *  - `<ContextMenu>`
 *  - `<ContextMenuPopover>`
 *
 * @see https://blueprintjs.com/docs/#core/components/context-menu-popover.imperative-api
 */
function showContextMenu(props, 
// eslint-disable-next-line @typescript-eslint/no-deprecated
options) {
    if (options === void 0) { options = {}; }
    var _a = maybeMigrateShowContextOptions(options), container = _a.container, render = _a.render;
    if (contextMenuState == null) {
        var element = document.createElement("div");
        element.classList.add(common_1.Classes.CONTEXT_MENU);
        container.appendChild(element);
        contextMenuState = { element: element, unmount: undefined };
    }
    else {
        // N.B. It's important to unmount previous instances of the ContextMenuPopover rendered by this function.
        // Otherwise, React will detect no change in props sent to the already-mounted component, and therefore
        // do nothing after the first call to this function, leading to bugs like https://github.com/palantir/blueprint/issues/5949
        contextMenuState.unmount();
    }
    contextMenuState.unmount = render(React.createElement(overlaysProvider_1.OverlaysProvider, null,
        React.createElement(UncontrolledContextMenuPopover, tslib_1.__assign({}, props))), contextMenuState.element);
}
exports.showContextMenu = showContextMenu;
function maybeMigrateShowContextOptions(
// eslint-disable-next-line @typescript-eslint/no-deprecated
options) {
    var _a, _b;
    if ("render" in options) {
        return {
            container: (_a = options.container) !== null && _a !== void 0 ? _a : document.body,
            render: options.render,
        };
    }
    return {
        container: (_b = options.container) !== null && _b !== void 0 ? _b : document.body,
        render: function (element, container) {
            var _a;
            // TODO(React 18): Replace deprecated ReactDOM methods. See: https://github.com/palantir/blueprint/issues/7165
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            var render = (_a = options.domRenderer) !== null && _a !== void 0 ? _a : ReactDOM.render;
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            render(element, container);
            return function () {
                var _a;
                // TODO(React 18): Replace deprecated ReactDOM methods. See: https://github.com/palantir/blueprint/issues/7165
                // eslint-disable-next-line @typescript-eslint/no-deprecated
                var unmount = (_a = options.domUnmounter) !== null && _a !== void 0 ? _a : ReactDOM.unmountComponentAtNode;
                unmount(container);
            };
        },
    };
}
/**
 * Hide a context menu that was created using `showContextMenu()`.
 *
 * Note that this API relies on global state in the @blueprintjs/core package, and should be used with caution.
 *
 * @see https://blueprintjs.com/docs/#core/components/context-menu-popover.imperative-api
 */
// eslint-disable-next-line @typescript-eslint/no-deprecated
function hideContextMenu(options) {
    if (options === void 0) { options = {}; }
    // TODO(React 18): Replace deprecated ReactDOM methods. See: https://github.com/palantir/blueprint/issues/7165
    // eslint-disable-next-line @typescript-eslint/no-deprecated
    var _a = options.domUnmounter, domUnmounter = _a === void 0 ? ReactDOM.unmountComponentAtNode : _a;
    if (contextMenuState != null) {
        if (domUnmounter != null) {
            domUnmounter(contextMenuState.element);
        }
        else {
            contextMenuState.unmount();
        }
        contextMenuState = undefined;
    }
}
exports.hideContextMenu = hideContextMenu;
/**
 * A simple wrapper around `ContextMenuPopover` which is open by default and uncontrolled.
 * It closes when a user clicks outside the popover.
 */
function UncontrolledContextMenuPopover(_a) {
    var onClose = _a.onClose, props = tslib_1.__rest(_a, ["onClose"]);
    var _b = React.useState(true), isOpen = _b[0], setIsOpen = _b[1];
    var handleClose = React.useCallback(function () {
        setIsOpen(false);
        onClose === null || onClose === void 0 ? void 0 : onClose();
    }, [onClose]);
    return React.createElement(contextMenuPopover_1.ContextMenuPopover, tslib_1.__assign({ isOpen: isOpen }, props, { onClose: handleClose }));
}
//# sourceMappingURL=contextMenuSingleton.js.map