import { Component, Element, Prop, Event, Watch, State, h } from '@stencil/core';
import { autoUpdate, computePosition, flip, offset, shift, size } from '@floating-ui/dom';
export class ScDropdown {
  constructor() {
    /** Indicates whether or not the dropdown is open. You can use this in lieu of the show/hide methods. */
    this.open = false;
    /** The placement of the dropdown. */
    this.placement = 'bottom-start';
    /** The distance in pixels from which to offset the panel away from its trigger. */
    this.distance = 10;
    /** The distance in pixels from which to offset the panel along its trigger. */
    this.skidding = 0;
    /**
     * Enable this option to prevent the panel from being clipped when the component is placed inside a container with
     * `overflow: auto|scroll`.
     */
    this.hoist = false;
    /** Determines whether the dropdown should hide when a menu item is selected */
    this.closeOnSelect = true;
  }
  handleOpenChange() {
    this.open ? this.show() : this.hide();
  }
  handleOutsideClick(evt) {
    const path = evt.composedPath();
    if (!path.some(item => {
      return item === this.el;
    })) {
      this.open = false;
    }
  }
  startPositioner() {
    this.stopPositioner();
    this.updatePositioner();
    this.positionerCleanup = autoUpdate(this.trigger, this.positioner, this.updatePositioner.bind(this));
  }
  updatePositioner() {
    if (!this.open || !this.trigger || !this.positioner) {
      return;
    }
    computePosition(this.trigger, this.positioner, {
      placement: this.placement,
      middleware: [
        offset({ mainAxis: this.distance, crossAxis: this.skidding }),
        flip(),
        shift(),
        size({
          apply: ({ availableWidth: width, availableHeight: height }) => {
            // Ensure the panel stays within the viewport when we have lots of menu items
            Object.assign(this.panel.style, {
              maxWidth: `${width}px`,
              maxHeight: `${height}px`,
            });
          },
          padding: 8,
        }),
      ],
      strategy: this.hoist ? 'fixed' : 'absolute',
    }).then(({ x, y, placement }) => {
      this.positioner.setAttribute('data-placement', placement);
      Object.assign(this.positioner.style, {
        position: this.hoist ? 'fixed' : 'absolute',
        left: `${x}px`,
        top: `${y}px`,
      });
    });
  }
  stopPositioner() {
    if (this.positionerCleanup) {
      this.positionerCleanup();
      this.positionerCleanup = undefined;
      this.positioner.removeAttribute('data-placement');
    }
  }
  show() {
    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
    if (this.isVisible) {
      return;
    }
    this.isVisible = true;
    this.open = true;
    this.startPositioner();
    this.panel.focus();
    this.scShow.emit();
  }
  hide() {
    // Prevent subsequent calls to the method, whether manually or triggered by the `open` watcher
    if (!this.isVisible) {
      return;
    }
    this.stopPositioner();
    this.isVisible = false;
    this.open = false;
    this.scHide.emit();
  }
  handleClick(e) {
    if (this.closeOnSelect) {
      const path = e.composedPath();
      if (path.some(item => {
        return item.classList && item.classList.contains('menu-item');
      })) {
        this.open = false;
      }
    }
  }
  componentWillLoad() {
    document.addEventListener('mousedown', evt => this.handleOutsideClick(evt));
  }
  /* Get the slotted menu */
  getMenu() {
    let slotted = this.el.shadowRoot.querySelector('slot');
    return slotted.assignedNodes().find(node => {
      return node.nodeName === 'sc-menu';
    });
  }
  render() {
    return (h("div", { class: {
        'dropdown': true,
        'dropdown--open': this.open,
        'dropdown--disabled': this.disabled,
      } },
      h("span", { part: "trigger", class: "dropdown__trigger", ref: el => (this.trigger = el), onClick: () => {
          if (this.disabled)
            return;
          if (this.open) {
            this.hide();
          }
          else {
            setTimeout(() => {
              this.show();
            }, 0);
          }
        }, "aria-expanded": "true", "aria-haspopup": "true" },
        h("slot", { name: "trigger" })),
      h("div", { class: "dropdown__positioner", ref: el => (this.positioner = el) },
        h("div", { part: "panel", class: {
            'dropdown__panel': true,
            'position--top-left': this.position === 'top-left',
            'position--top-right': this.position === 'top-right',
            'position--bottom-left': this.position === 'bottom-left',
            'position--bottom-right': this.position === 'bottom-right',
          }, role: "menu", "aria-orientation": "vertical", "aria-labelledby": "menu-button", tabindex: "-1", onClick: e => this.handleClick(e), ref: el => (this.panel = el) },
          h("slot", null)))));
  }
  static get is() { return "sc-dropdown"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["dropdown.scss"]
  }; }
  static get styleUrls() { return {
    "$": ["dropdown.css"]
  }; }
  static get properties() { return {
    "clickEl": {
      "type": "unknown",
      "mutable": false,
      "complexType": {
        "original": "HTMLElement",
        "resolved": "HTMLElement",
        "references": {
          "HTMLElement": {
            "location": "global"
          }
        }
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": ""
      }
    },
    "disabled": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Is this disabled."
      },
      "attribute": "disabled",
      "reflect": false
    },
    "open": {
      "type": "boolean",
      "mutable": true,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": true,
      "docs": {
        "tags": [],
        "text": "Indicates whether or not the dropdown is open. You can use this in lieu of the show/hide methods."
      },
      "attribute": "open",
      "reflect": true,
      "defaultValue": "false"
    },
    "position": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'",
        "resolved": "\"bottom-left\" | \"bottom-right\" | \"top-left\" | \"top-right\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The placement of the dropdown panel"
      },
      "attribute": "position",
      "reflect": false
    },
    "placement": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "| 'top'\n    | 'top-start'\n    | 'top-end'\n    | 'bottom'\n    | 'bottom-start'\n    | 'bottom-end'\n    | 'right'\n    | 'right-start'\n    | 'right-end'\n    | 'left'\n    | 'left-start'\n    | 'left-end'",
        "resolved": "\"bottom\" | \"bottom-end\" | \"bottom-start\" | \"left\" | \"left-end\" | \"left-start\" | \"right\" | \"right-end\" | \"right-start\" | \"top\" | \"top-end\" | \"top-start\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The placement of the dropdown."
      },
      "attribute": "placement",
      "reflect": true,
      "defaultValue": "'bottom-start'"
    },
    "distance": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The distance in pixels from which to offset the panel away from its trigger."
      },
      "attribute": "distance",
      "reflect": false,
      "defaultValue": "10"
    },
    "skidding": {
      "type": "number",
      "mutable": false,
      "complexType": {
        "original": "number",
        "resolved": "number",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The distance in pixels from which to offset the panel along its trigger."
      },
      "attribute": "skidding",
      "reflect": false,
      "defaultValue": "0"
    },
    "hoist": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Enable this option to prevent the panel from being clipped when the component is placed inside a container with\n`overflow: auto|scroll`."
      },
      "attribute": "hoist",
      "reflect": false,
      "defaultValue": "false"
    },
    "closeOnSelect": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Determines whether the dropdown should hide when a menu item is selected"
      },
      "attribute": "close-on-select",
      "reflect": true,
      "defaultValue": "true"
    }
  }; }
  static get states() { return {
    "isVisible": {}
  }; }
  static get events() { return [{
      "method": "scShow",
      "name": "scShow",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emitted when the dropdown opens. Calling `event.preventDefault()` will prevent it from being opened."
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scHide",
      "name": "scHide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": "Emitted when the dropdown closes. Calling `event.preventDefault()` will prevent it from being closed."
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }]; }
  static get elementRef() { return "el"; }
  static get watchers() { return [{
      "propName": "open",
      "methodName": "handleOpenChange"
    }]; }
}
