import { defineComponent, mergeModels, useModel, inject, computed, useTemplateRef, ref, toRef, watch, provide, readonly, createBlock, openBlock, unref, normalizeClass, withCtx, createVNode, createCommentVNode, renderSlot, createTextVNode, toDisplayString, createElementVNode, Transition, mergeProps, withDirectives, normalizeStyle, vShow, nextTick } from "vue";
import { i as isBoundary, a as isRootBoundary, o as offset, f as flip, s as shift, b as size, u as useFloating, r as resolveBootstrapCaret, c as autoUpdate } from "./floatingUi-DTn-0etm.mjs";
import { o as onKeyStroke, a as onClickOutside } from "./index-nMtnPEP0.mjs";
import { u as useDefaults } from "./useDefaults-DvqfKEoD.mjs";
import { u as useId } from "./useId-9_HUwM96.mjs";
import { _ as _sfc_main$2 } from "./BButton.vue_vue_type_script_setup_true_lang-mC3U3Kza.mjs";
import { _ as _sfc_main$1 } from "./ConditionalWrapper.vue_vue_type_script_lang-IX_NpHH-.mjs";
import { _ as _sfc_main$3 } from "./ConditionalTeleport.vue_vue_type_script_lang-Cp-egLmm.mjs";
import { g as getElement } from "./getElement-DrDVR-jO.mjs";
import { i as inputGroupKey, b as buttonGroupKey, d as dropdownInjectionKey } from "./keys-D5Pj1dmf.mjs";
import { u as useShowHide } from "./useShowHide-rIwHwrmD.mjs";
import { u as useToNumber } from "./index-DX8Yoi0C.mjs";
const _hoisted_1 = { class: "visually-hidden" };
const _hoisted_2 = ["id", "aria-labelledby", "role"];
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "BDropdown",
  props: /* @__PURE__ */ mergeModels({
    ariaLabel: { default: void 0 },
    autoClose: { type: [Boolean, String], default: true },
    boundary: { default: "clippingAncestors" },
    boundaryPadding: { default: void 0 },
    disabled: { type: Boolean, default: false },
    floatingMiddleware: { default: void 0 },
    icon: { type: Boolean, default: false },
    id: { default: void 0 },
    isNav: { type: Boolean, default: false },
    menuClass: { default: void 0 },
    noCaret: { type: Boolean, default: false },
    noFlip: { type: Boolean, default: false },
    noShift: { type: Boolean, default: false },
    noSize: { type: Boolean, default: false },
    offset: { default: 0 },
    role: { default: "menu" },
    size: { default: "md" },
    noWrapper: { type: Boolean, default: false },
    split: { type: Boolean, default: false },
    splitButtonType: { default: "button" },
    splitClass: { default: void 0 },
    splitDisabled: { type: Boolean, default: void 0 },
    splitHref: { default: void 0 },
    splitTo: { default: void 0 },
    splitVariant: { default: void 0 },
    strategy: { default: "absolute" },
    text: { default: void 0 },
    toggleClass: { default: void 0 },
    toggleText: { default: "Toggle dropdown" },
    variant: { default: "secondary" },
    wrapperClass: { default: void 0 },
    placement: { default: "bottom-start" },
    teleportDisabled: { type: Boolean, default: false },
    teleportTo: { default: void 0 },
    initialAnimation: { type: Boolean, default: false },
    noAnimation: { type: Boolean },
    noFade: { type: Boolean, default: false },
    lazy: { type: Boolean, default: false },
    unmountLazy: { type: Boolean, default: false },
    show: { type: Boolean, default: false },
    transProps: { default: void 0 },
    visible: { type: Boolean, default: false }
  }, {
    "modelValue": { type: Boolean, ...{ default: false } },
    "modelModifiers": {}
  }),
  emits: /* @__PURE__ */ mergeModels(["split-click", "hide", "hide-prevented", "hidden", "show", "show-prevented", "shown", "toggle", "toggle-prevented"], ["update:modelValue"]),
  setup(__props, { expose: __expose, emit: __emit }) {
    const _props = __props;
    const props = useDefaults(_props, "BDropdown");
    const emit = __emit;
    const computedId = useId(() => props.id, "dropdown");
    const modelValue = useModel(__props, "modelValue");
    const inInputGroup = inject(inputGroupKey, false);
    const inButtonGroup = inject(buttonGroupKey, false);
    const computedOffset = computed(
      () => typeof props.offset === "string" || typeof props.offset === "number" ? props.offset : Number.NaN
    );
    const offsetToNumber = useToNumber(computedOffset);
    const floatingElement = useTemplateRef("_floating");
    const button = useTemplateRef("_button");
    const splitButton = useTemplateRef("_splitButton");
    const boundary = computed(
      () => isBoundary(props.boundary) ? props.boundary : void 0
    );
    const rootBoundary = computed(
      () => isRootBoundary(props.boundary) ? props.boundary : void 0
    );
    const referenceElement = computed(() => !props.split ? splitButton.value : button.value);
    let cleanup;
    const {
      showRef,
      renderRef,
      hide,
      show,
      toggle,
      computedNoAnimation,
      transitionProps,
      contentShowing,
      isVisible
    } = useShowHide(modelValue, props, emit, referenceElement, computedId, {
      showFn: () => {
        update();
        nextTick(() => {
          cleanup = autoUpdate(
            referenceElement.value,
            floatingElement.value,
            update,
            {
              animationFrame: false
            }
          );
        });
      },
      hideFn: () => {
        if (cleanup) {
          cleanup();
          cleanup = void 0;
        }
      }
    });
    const computedMenuClasses = computed(() => [
      {
        show: isVisible.value,
        fade: !computedNoAnimation.value
      }
    ]);
    onKeyStroke(
      "Escape",
      () => {
        hide();
        getElement(referenceElement.value)?.focus();
      },
      { target: referenceElement }
    );
    onKeyStroke(
      "Escape",
      () => {
        hide();
        getElement(referenceElement.value)?.focus();
      },
      { target: floatingElement }
    );
    const keynav = (e, v) => {
      if (floatingElement.value?.contains(e.target?.closest("form"))) return;
      if (/input|select|option|textarea|form/i.test(e.target?.tagName)) return;
      e.preventDefault();
      if (!showRef.value) {
        show();
        const loop = setInterval(() => {
          if (isVisible.value) {
            clearInterval(loop);
            nextTick(() => keynav(e, v));
          }
        }, 16);
        return;
      }
      const list = floatingElement.value?.querySelectorAll(
        ".dropdown-item:not(.disabled):not(:disabled)"
      );
      if (!list) return;
      if (floatingElement.value?.contains(document.activeElement)) {
        const active = floatingElement.value.querySelector(".dropdown-item:focus");
        const index = Array.prototype.indexOf.call(list, active) + v;
        if (index >= 0 && index < list?.length) list[index]?.focus();
      } else {
        list[v === -1 ? list.length - 1 : 0]?.focus();
      }
    };
    onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: referenceElement });
    onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: referenceElement });
    onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: floatingElement });
    onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: floatingElement });
    const sizeStyles = ref({});
    const floatingMiddleware = computed(() => {
      if (props.floatingMiddleware !== void 0) {
        return props.floatingMiddleware;
      }
      const localOffset = typeof props.offset === "string" || typeof props.offset === "number" ? offsetToNumber.value : props.offset;
      const arr = [offset(localOffset)];
      if (props.noFlip === false) {
        arr.push(
          flip({
            boundary: boundary.value,
            rootBoundary: rootBoundary.value,
            padding: props.boundaryPadding
          })
        );
      }
      if (props.noShift === false) {
        arr.push(
          shift({
            boundary: boundary.value,
            rootBoundary: rootBoundary.value,
            padding: props.boundaryPadding
          })
        );
      }
      if (props.noSize === false) {
        arr.push(
          size({
            boundary: boundary.value,
            rootBoundary: rootBoundary.value,
            padding: props.boundaryPadding,
            apply({ availableWidth, availableHeight }) {
              sizeStyles.value = {
                "--bv-floating-max-height": availableHeight >= (floatingElement.value?.scrollHeight ?? 0) ? void 0 : availableHeight ? `${Math.max(0, availableHeight)}px` : void 0,
                "--bv-floating-max-width": availableWidth >= (floatingElement.value?.scrollWidth ?? 0) ? void 0 : availableWidth ? `${Math.max(0, availableWidth)}px` : void 0
              };
            }
          })
        );
      }
      return arr;
    });
    const { update, floatingStyles } = useFloating(referenceElement, floatingElement, {
      placement: () => props.placement,
      middleware: floatingMiddleware,
      strategy: toRef(() => props.strategy)
    });
    const inButtonGroupAttributes = inButtonGroup ? {
      class: "btn-group",
      role: "group"
    } : void 0;
    const computedClasses = computed(() => [
      inButtonGroupAttributes?.class,
      props.wrapperClass,
      {
        "btn-group": !props.wrapperClass && props.split,
        [`drop${resolveBootstrapCaret(props.placement)}`]: !props.wrapperClass,
        "position-static": props.boundary !== "clippingAncestors" && !props.isNav
      }
    ]);
    const buttonClasses = computed(() => [
      props.split ? props.splitClass : props.toggleClass,
      {
        "nav-link": props.isNav,
        "dropdown-toggle": !props.split,
        "dropdown-toggle-no-caret": props.noCaret && !props.split,
        "show": props.split ? void 0 : showRef.value
      }
    ]);
    const onButtonClick = () => {
      toggle();
    };
    const onSplitClick = (event) => {
      if (props.split) {
        emit("split-click", event);
        return;
      }
      onButtonClick();
    };
    onClickOutside(
      floatingElement,
      () => {
        if (showRef.value && (props.autoClose === true || props.autoClose === "outside")) {
          hide();
        }
      },
      { ignore: [button, splitButton] }
    );
    const onClickInside = () => {
      if (showRef.value && (props.autoClose === true || props.autoClose === "inside")) {
        hide();
      }
    };
    watch(isVisible, () => {
      update();
    });
    __expose({
      hide,
      show,
      toggle
    });
    provide(dropdownInjectionKey, {
      id: computedId,
      show,
      hide,
      toggle,
      visible: readonly(showRef),
      isNav: toRef(() => props.isNav)
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$1, {
        skip: unref(inInputGroup) || unref(props).noWrapper,
        class: normalizeClass(computedClasses.value),
        role: unref(inButtonGroupAttributes)?.role
      }, {
        default: withCtx(() => [
          createVNode(_sfc_main$2, {
            id: unref(computedId),
            ref: "_splitButton",
            variant: unref(props).splitVariant || unref(props).variant,
            size: unref(props).size,
            class: normalizeClass(buttonClasses.value),
            disabled: unref(props).splitDisabled || unref(props).disabled,
            type: unref(props).splitButtonType,
            "aria-label": unref(props).ariaLabel,
            "aria-expanded": unref(props).split ? void 0 : unref(showRef),
            "aria-haspopup": unref(props).split ? void 0 : "menu",
            href: unref(props).split ? unref(props).splitHref : void 0,
            icon: unref(props).icon,
            to: unref(props).split && unref(props).splitTo ? unref(props).splitTo : void 0,
            onClick: onSplitClick
          }, {
            default: withCtx(() => [
              renderSlot(_ctx.$slots, "button-content", {}, () => [
                createTextVNode(toDisplayString(unref(props).text), 1)
              ])
            ]),
            _: 3
          }, 8, ["id", "variant", "size", "class", "disabled", "type", "aria-label", "aria-expanded", "aria-haspopup", "href", "icon", "to"]),
          unref(props).split ? (openBlock(), createBlock(_sfc_main$2, {
            key: 0,
            id: unref(computedId) + "-split",
            ref: "_button",
            variant: unref(props).variant,
            size: unref(props).size,
            disabled: unref(props).disabled,
            class: normalizeClass([[unref(props).toggleClass, { show: unref(showRef) }], "dropdown-toggle-split dropdown-toggle"]),
            "aria-expanded": unref(showRef),
            "aria-haspopup": "menu",
            onClick: onButtonClick
          }, {
            default: withCtx(() => [
              createElementVNode("span", _hoisted_1, [
                renderSlot(_ctx.$slots, "toggle-text", {}, () => [
                  createTextVNode(toDisplayString(unref(props).toggleText), 1)
                ])
              ])
            ]),
            _: 3
          }, 8, ["id", "variant", "size", "disabled", "class", "aria-expanded"])) : createCommentVNode("", true),
          createVNode(_sfc_main$3, {
            to: unref(props).teleportTo,
            disabled: !unref(props).teleportTo || unref(props).teleportDisabled
          }, {
            default: withCtx(() => [
              unref(renderRef) || unref(contentShowing) ? (openBlock(), createBlock(Transition, mergeProps({ key: 0 }, unref(transitionProps), {
                appear: modelValue.value || unref(props).visible
              }), {
                default: withCtx(() => [
                  withDirectives(createElementVNode("ul", {
                    id: unref(computedId) + "-menu",
                    ref: "_floating",
                    style: normalizeStyle([unref(floatingStyles), sizeStyles.value, { display: unref(showRef) ? "block" : "none" }]),
                    class: normalizeClass(["dropdown-menu overflow-auto b-floating-size", [unref(props).menuClass, computedMenuClasses.value]]),
                    "aria-labelledby": unref(computedId),
                    role: unref(props).role,
                    onClick: onClickInside
                  }, [
                    unref(contentShowing) ? renderSlot(_ctx.$slots, "default", {
                      key: 0,
                      id: unref(computedId),
                      hide: unref(hide),
                      show: unref(show),
                      visible: unref(showRef),
                      click: onClickInside,
                      toggle: onButtonClick,
                      active: unref(showRef)
                    }) : createCommentVNode("", true)
                  ], 14, _hoisted_2), [
                    [vShow, unref(showRef)]
                  ])
                ]),
                _: 3
              }, 16, ["appear"])) : createCommentVNode("", true)
            ]),
            _: 3
          }, 8, ["to", "disabled"])
        ]),
        _: 3
      }, 8, ["skip", "class", "role"]);
    };
  }
});
export {
  _sfc_main as _
};
//# sourceMappingURL=BDropdown.vue_vue_type_script_setup_true_lang-DQ4P7ijv.mjs.map
