import a from "../../common/mixins/keyboard-list-navigation.js";
import { DROPDOWN_PADDING_CLASSES as o } from "./dropdown-constants.js";
import { getUniqueString as l } from "../../common/utils/index.js";
import { EVENT_KEYNAMES as i } from "../../common/constants/index.js";
import { n as h } from "../../_plugin-vue2_normalizer-DSLOjnn3.js";
import d from "../popover/popover.js";
import { LIST_ITEM_NAVIGATION_TYPES as r } from "../list-item/list-item-constants.js";
import { POPOVER_APPEND_TO_VALUES as p } from "../popover/popover-constants.js";
const u = {
  name: "DtDropdown",
  components: {
    DtPopover: d
  },
  mixins: [
    a({
      indexKey: "highlightIndex",
      idKey: "highlightId",
      listElementKey: "getListElement",
      listItemRole: "menuitem",
      afterHighlightMethod: "afterHighlight",
      beginningOfListMethod: "beginningOfListMethod",
      endOfListMethod: "endOfListMethod",
      activeItemKey: "activeItemEl",
      focusOnKeyboardNavigation: !0
    })
  ],
  props: {
    /**
     * Controls whether the dropdown is shown. Leaving this null will have the dropdown trigger on click by default.
     * If you set this value, the default trigger behavior will be disabled and you can control it as you need.
     * Supports .sync modifier
     */
    open: {
      type: Boolean,
      default: null
    },
    /**
     * Opens the dropdown on right click (context menu). If you set this value to `true`,
     * the default trigger behavior will be disabled.
     */
    openOnContext: {
      type: Boolean,
      default: !1
    },
    /**
     * Vertical padding size around the list element.
     * @values none, small, large
     */
    padding: {
      type: String,
      default: "small",
      validator: (e) => Object.keys(o).some((t) => t === e)
    },
    /**
     * Determines modal state, dropdown has a modal overlay preventing interaction with elements
     * below it, but it is invisible.
     */
    modal: {
      type: Boolean,
      default: !0
    },
    /**
     * Width configuration for the popover content. When its value is 'anchor',
     * the popover content will have the same width as the anchor.
     * @values null, anchor
     */
    contentWidth: {
      type: String,
      default: null
    },
    /**
     * Determines maximum height for the popover before overflow.
     * Possible units rem|px|em
     */
    maxHeight: {
      type: String,
      default: ""
    },
    /**
     * Determines maximum width for the popover before overflow.
     * Possible units rem|px|%|em
     */
    maxWidth: {
      type: String,
      default: ""
    },
    /**
     * Sets an ID on the list element of the component. Used by several aria attributes
     * as well as when deriving the IDs for each item.
     */
    listId: {
      type: String,
      default() {
        return l();
      }
    },
    /**
     * The type of navigation that this component should support.
     * - "arrow-keys" for items that are navigated with UP/DOWN keys.
     * - "tab" for items that are navigated using the TAB key.
     * - "none" for static items that are not interactive.
     * @values arrow-keys, tab, none
     */
    navigationType: {
      type: String,
      default: r.ARROW_KEYS,
      validator: (e) => Object.values(r).includes(e)
    },
    /**
     * If the dropdown does not fit in the direction described by "placement",
     * it will attempt to change it's direction to the "fallbackPlacements".
     *
     * @values top, top-start, top-end,
     * right, right-start, right-end,
     * left, left-start, left-end,
     * bottom, bottom-start, bottom-end,
     * auto, auto-start, auto-end
     * */
    fallbackPlacements: {
      type: Array,
      default: () => ["auto"]
    },
    /**
     * The direction the dropdown displays relative to the anchor.
     */
    placement: {
      type: String,
      default: "bottom"
    },
    /**
     * A method that will be called when the selection goes past the beginning of the list.
     */
    onBeginningOfList: {
      type: Function,
      default: null
    },
    /**
     * A method that will be called when the selection goes past the end of the list.
     */
    onEndOfList: {
      type: Function,
      default: null
    },
    /**
     * Additional class for the wrapper list element.
     */
    listClass: {
      type: [String, Array, Object],
      default: ""
    },
    /**
     * Sets the element to which the popover is going to append to.
     * 'body' will append to the nearest body (supports shadow DOM).
     * @values 'body', 'parent', HTMLElement,
     */
    appendTo: {
      type: [HTMLElement, String],
      default: "body",
      validator: (e) => p.includes(e) || e instanceof HTMLElement
    },
    /**
     * If set to false the dialog will display over top of the anchor when there is insufficient space.
     * If set to true it will never move from its position relative to the anchor and will clip instead.
     * <a
     *   class="d-link"
     *   href="https://popper.js.org/docs/v2/modifiers/prevent-overflow/#tether"
     *   target="_blank"
     * >
     *   Popper.js docs
     * </a>
     * @values true, false
     */
    tether: {
      type: Boolean,
      default: !0
    },
    /**
     * Named transition when the content display is toggled.
     * @see DtLazyShow
     */
    transition: {
      type: String,
      default: "fade"
    }
  },
  emits: [
    /**
     * Event fired when the highlight changes
     *
     * @event highlight
     * @type {Number}
     */
    "highlight",
    /**
     * Event fired when dropdown is shown or hidden
     *
     * @event opened
     * @type {Boolean | Array}
     */
    "opened",
    /**
     * Event fired to sync the open prop with the parent component
     * @event update:open
     */
    "update:open"
  ],
  data() {
    return {
      LIST_ITEM_NAVIGATION_TYPES: r,
      DROPDOWN_PADDING_CLASSES: o,
      EVENT_KEYNAMES: i,
      openedWithKeyboard: !1,
      isOpen: null
    };
  },
  computed: {
    dropdownListeners() {
      return {
        ...this.$listeners,
        opened: (e) => {
          this.updateInitialHighlightIndex(e);
        },
        keydown: (e) => {
          switch (e.code) {
            case i.up:
            case i.arrowup:
              this.onUpKeyPress(e), e.stopPropagation(), e.preventDefault();
              break;
            case i.down:
            case i.arrowdown:
              this.onDownKeyPress(e), e.stopPropagation(), e.preventDefault();
              break;
            case i.space:
            case i.spacebar:
              this.onSpaceKey();
              break;
            case i.enter:
              this.onEnterKey();
              break;
            case i.home:
              this.onHomeKeyPress(e), e.stopPropagation(), e.preventDefault();
              break;
            case i.end:
              this.onEndKeyPress(e), e.stopPropagation(), e.preventDefault();
              break;
            default:
              this.onKeyPress(e);
              break;
          }
          this.$emit("keydown", e);
        }
      };
    },
    beginningOfListMethod() {
      return this.onBeginningOfList || this.jumpToEnd;
    },
    endOfListMethod() {
      return this.onEndOfList || this.jumpToBeginning;
    },
    activeItemEl() {
      return this.getListElement().querySelector("#" + this.highlightId);
    },
    isArrowKeyNav() {
      return this.navigationType === this.LIST_ITEM_NAVIGATION_TYPES.ARROW_KEYS;
    },
    listClasses() {
      return [
        "d-dropdown-list",
        o[this.padding],
        this.listClass,
        { "d-context-menu-list": this.openOnContext }
      ];
    },
    shouldOpenWithArrowKeys() {
      return !this.openOnContext;
    }
  },
  methods: {
    onMouseHighlight(e) {
      const t = e.target.closest("li");
      t && t.role && this.highlightId !== t.id && (this.setHighlightId(t.id), t.focus());
    },
    getListElement() {
      return this.$refs.listWrapper;
    },
    clearHighlightIndex() {
      this.setHighlightIndex(-1);
    },
    afterHighlight() {
      this.highlightIndex !== this._itemsLength() - 1 && this.$emit("highlight", this.highlightIndex);
    },
    updateInitialHighlightIndex(e) {
      this.isOpen = e, e ? (this.openedWithKeyboard && this.isArrowKeyNav && this.setHighlightIndex(0), this.$emit("opened", !0)) : (this.clearHighlightIndex(), this.openedWithKeyboard = !1, this.$emit("opened", !1));
    },
    onSpaceKey() {
      this.open || (this.openedWithKeyboard = !0);
    },
    onEnterKey() {
      this.open || (this.openedWithKeyboard = !0);
    },
    onUpKeyPress() {
      if (!this.isOpen) {
        this.openedWithKeyboard = !0;
        return;
      }
      if (this.isArrowKeyNav)
        return this.onUpKey();
    },
    onDownKeyPress() {
      if (!this.isOpen) {
        this.openedWithKeyboard = !0;
        return;
      }
      if (this.isArrowKeyNav)
        return this.onDownKey();
    },
    onHomeKeyPress() {
      if (!(!this.isOpen || !this.isArrowKeyNav))
        return this.onHomeKey();
    },
    onEndKeyPress() {
      if (!(!this.isOpen || !this.isArrowKeyNav))
        return this.onEndKey();
    },
    onKeyPress(e) {
      if (!(!this.isOpen || !this.isArrowKeyNav || !this.isValidLetter(e.key)))
        return e.stopPropagation(), e.preventDefault(), this.onNavigationKey(e.key);
    }
  }
};
var g = function() {
  var t = this, s = t._self._c;
  return s("dt-popover", t._g({ ref: "popover", attrs: { "content-width": t.contentWidth, open: t.open, placement: t.placement, "initial-focus-element": t.openedWithKeyboard ? "first" : "dialog", "fallback-placements": t.fallbackPlacements, padding: "none", role: "menu", "append-to": t.appendTo, modal: t.modal, "max-height": t.maxHeight, "max-width": t.maxWidth, "open-with-arrow-keys": t.shouldOpenWithArrowKeys, "open-on-context": t.openOnContext, tether: t.tether, transition: t.transition }, scopedSlots: t._u([{ key: "anchor", fn: function({ attrs: n }) {
    return [t._t("anchor", null, null, n)];
  } }, { key: "content", fn: function({ close: n }) {
    return [s("ul", { ref: "listWrapper", class: t.listClasses, attrs: { id: t.listId, "data-qa": "dt-dropdown-list-wrapper" }, on: { mouseleave: t.clearHighlightIndex, "!mousemove": function(y) {
      return t.onMouseHighlight.apply(null, arguments);
    } } }, [t._t("list", null, { close: n })], 2)];
  } }, { key: "footerContent", fn: function({ close: n }) {
    return [t._t("footer", null, { close: n })];
  } }], null, !0) }, t.dropdownListeners));
}, f = [], m = /* @__PURE__ */ h(
  u,
  g,
  f
);
const x = m.exports;
export {
  x as default
};
//# sourceMappingURL=dropdown.js.map
