import { Corner, MDCMenuSurface } from "@material/menu-surface";
import { h, } from "@stencil/core";
import { isDescendant } from "../../util/dom";
import { ESCAPE, TAB } from "../../util/keycodes";
/**
 * @slot - Content to put inside the surface
 * @private
 */
export class MenuSurface {
    constructor() {
        /**
         * True if the menu surface is open, false otherwise
         */
        this.open = false;
        this.setup = () => {
            const menuElement = this.host.shadowRoot.querySelector('.mdc-menu-surface');
            if (!menuElement) {
                return;
            }
            this.menuSurface = new MDCMenuSurface(menuElement);
            this.menuSurface.setAnchorCorner(Corner.TOP_START);
            document.addEventListener('mousedown', this.handleDocumentClick, {
                capture: true,
            });
            this.host.addEventListener('keydown', this.handleKeyDown);
        };
        this.teardown = () => {
            var _a;
            (_a = this.menuSurface) === null || _a === void 0 ? void 0 : _a.destroy();
            document.removeEventListener('mousedown', this.handleDocumentClick, {
                capture: true,
            });
            this.host.removeEventListener('keydown', this.handleKeyDown);
        };
        this.handleDocumentClick = (event) => {
            const elementPath = event.composedPath ? event.composedPath() : [];
            if (!this.open) {
                return;
            }
            if (isDescendant(event.target, this.host)) {
                return;
            }
            if (this.allowClicksElement) {
                const clickedInAllowedElement = elementPath.includes(this.allowClicksElement);
                if (clickedInAllowedElement) {
                    return;
                }
            }
            this.dismiss.emit();
            this.preventClickEventPropagation();
        };
        this.preventClickEventPropagation = () => {
            // When the menu surface is open, we want to stop the `click` event from propagating
            // when clicking outside the surface itself. This is to prevent any dialog that might
            // be open from closing, etc. However, when dragging a scrollbar no `click` event is emitted,
            // only mousedown and mouseup. So we listen for `mousedown` and attach a one-time listener
            // for `click`, so we can capture and "kill" it.
            document.addEventListener('click', this.stopEvent, {
                capture: true,
                once: true,
            });
            // We also capture and "kill" the next `mouseup` event.
            document.addEventListener('mouseup', this.stopEvent, {
                capture: true,
                once: true,
            });
            // If the user dragged the scrollbar, no `click` event happens. So when we get the
            // `mouseup` event, remove the handler for `click` if it's still there.
            // Otherwise, we would catch the next click even though the menu is no longer open.
            document.addEventListener('mouseup', () => {
                document.removeEventListener('click', this.stopEvent, {
                    capture: true,
                });
            }, {
                once: true,
            });
        };
        this.stopEvent = (event) => {
            event.stopPropagation();
            event.preventDefault();
        };
        this.handleKeyDown = (event) => {
            const isEscape = event.key === ESCAPE;
            const isTab = event.key === TAB;
            if (this.open && (isEscape || isTab)) {
                event.stopPropagation();
                this.dismiss.emit();
            }
        };
    }
    connectedCallback() {
        this.setup();
    }
    disconnectedCallback() {
        this.teardown();
    }
    componentDidLoad() {
        this.setup();
    }
    render() {
        const classList = {
            'mdc-menu': true,
            'mdc-menu-surface': true,
            'mdc-menu-surface--open': this.open,
            'mdc-elevation-transition': true,
            'mdc-elevation--z4': true,
        };
        return (h("div", { key: 'd00fdc8b36fb54a29a2a310ddbc2f589ce34bce3', class: classList, tabindex: "-1" }, h("slot", { key: 'd134575dc508794b42fed852e952a7d12c399b2a' })));
    }
    static get is() { return "limel-menu-surface"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["menu-surface.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["menu-surface.css"]
        };
    }
    static get properties() {
        return {
            "open": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "True if the menu surface is open, false otherwise"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "open",
                "defaultValue": "false"
            },
            "allowClicksElement": {
                "type": "unknown",
                "mutable": false,
                "complexType": {
                    "original": "HTMLElement",
                    "resolved": "HTMLElement",
                    "references": {
                        "HTMLElement": {
                            "location": "global",
                            "id": "global::HTMLElement"
                        }
                    }
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Clicks in this element should not be prevented when the menu surface is open"
                },
                "getter": false,
                "setter": false
            }
        };
    }
    static get events() {
        return [{
                "method": "dismiss",
                "name": "dismiss",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the menu surface is dismissed and should be closed"
                },
                "complexType": {
                    "original": "void",
                    "resolved": "void",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "host"; }
}
