import { getCurrentInstance, watch, computed, toValue, inject, defineComponent, mergeModels, useSlots, useModel, useTemplateRef, ref, onMounted, nextTick, createBlock, openBlock, unref, withCtx, createCommentVNode, renderSlot, Transition, mergeProps, withDirectives, createElementVNode, withModifiers, createElementBlock, normalizeClass, normalizeProps, guardReactiveProps, resolveDynamicComponent, createTextVNode, toDisplayString, Fragment, createVNode, vShow, normalizeStyle } from "vue";
import { m as getSSRHandler, e as unrefElement, o as onKeyStroke } from "./index-nMtnPEP0.mjs";
import { a as useActivatedFocusTrap, u as useSafeScrollLock } from "./useSafeScrollLock-BMtL1rUG.mjs";
import { _ as _sfc_main$2 } from "./BButton.vue_vue_type_script_setup_true_lang-mC3U3Kza.mjs";
import { _ as _sfc_main$3 } from "./BCloseButton.vue_vue_type_script_setup_true_lang-CezXiDAc.mjs";
import { u as useDefaults } from "./useDefaults-DvqfKEoD.mjs";
import { u as useId } from "./useId-9_HUwM96.mjs";
import { i as isEmptySlot, c as getModalZIndex } from "./dom-DVb-f0ZG.mjs";
import { u as useColorVariantClasses } from "./useColorVariantClasses-ZDE19TZw.mjs";
import { m as modalManagerKey } from "./keys-D5Pj1dmf.mjs";
import { h as tryOnScopeDispose } from "./index-DX8Yoi0C.mjs";
import { u as useShowHide } from "./useShowHide-rIwHwrmD.mjs";
import { _ as _sfc_main$1 } from "./ConditionalTeleport.vue_vue_type_script_lang-Cp-egLmm.mjs";
import { g as getElement } from "./getElement-DrDVR-jO.mjs";
const modalOpenClassName = "modal-open";
const useSharedModalStack = () => {
  const modalManagerPlugin = inject(modalManagerKey, null);
  const dispose = (modal) => {
    modalManagerPlugin?.removeStack(modal);
    modalManagerPlugin?.removeRegistry(modal);
  };
  const updateHTMLAttrs = getSSRHandler("updateHTMLAttrs", (selector, attribute, value) => {
    const el = typeof selector === "string" ? window?.document.querySelector(selector) : unrefElement(selector);
    if (!el) return;
    if (attribute === "class") {
      el.classList.toggle(modalOpenClassName, value === modalOpenClassName);
    } else {
      el.setAttribute(attribute, value);
    }
  });
  tryOnScopeDispose(() => {
    if (modalManagerPlugin?.countStack.value === 0) {
      updateHTMLAttrs("body", "class", "");
    }
  });
  watch(
    () => modalManagerPlugin?.countStack.value,
    (newValue) => {
      if (newValue === void 0) return;
      updateHTMLAttrs("body", "class", newValue > 0 ? modalOpenClassName : "");
    }
  );
  return {
    ...modalManagerPlugin,
    dispose
  };
};
const useModalManager = (modalOpen, initialValue) => {
  const { pushRegistry, pushStack, removeStack, stack, dispose, countStack } = useSharedModalStack();
  const currentModal = getCurrentInstance();
  if (!currentModal || currentModal.type.__name !== "BModal") {
    throw new Error("useModalManager must only use in BModal component");
  }
  pushRegistry?.(currentModal);
  tryOnScopeDispose(() => {
    dispose(currentModal);
  });
  const setInStack = (newValue, oldValue) => {
    if (newValue) {
      pushStack?.(currentModal);
    } else if (oldValue && !newValue) {
      removeStack?.(currentModal);
    }
  };
  setInStack(initialValue, initialValue);
  watch(modalOpen, setInStack);
  return {
    activePosition: computed(
      () => stack?.value.findIndex((el) => toValue(el.exposed?.id) === toValue(currentModal.exposed?.id))
    ),
    activeModalCount: countStack,
    stackWithoutSelf: computed(
      () => stack?.value.filter(
        (el) => toValue(el.exposed?.id) !== toValue(currentModal.exposed?.id)
      ) ?? []
    )
  };
};
const _hoisted_1 = ["id", "aria-labelledby", "aria-describedby"];
const _hoisted_2 = ["id"];
const fallbackClassSelector = "modal-fallback-focus";
const _sfc_main = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "BModal",
  props: /* @__PURE__ */ mergeModels({
    focus: { type: [String, Boolean, Object, null], default: void 0 },
    backdropFirst: { type: Boolean, default: false },
    body: { default: void 0 },
    bodyAttrs: { default: void 0 },
    bodyBgVariant: { default: null },
    bodyClass: { default: null },
    bodyScrolling: { type: Boolean, default: false },
    bodyTextVariant: { default: null },
    bodyVariant: { default: null },
    busy: { type: Boolean, default: false },
    buttonSize: { default: "md" },
    cancelClass: { default: void 0 },
    cancelDisabled: { type: Boolean, default: false },
    cancelTitle: { default: "Cancel" },
    cancelVariant: { default: "secondary" },
    centered: { type: Boolean, default: false },
    contentClass: { default: void 0 },
    dialogClass: { default: void 0 },
    footerBgVariant: { default: null },
    footerBorderVariant: { default: null },
    footerClass: { default: void 0 },
    footerTextVariant: { default: null },
    footerVariant: { default: null },
    fullscreen: { type: [Boolean, String], default: false },
    headerAttrs: { default: void 0 },
    headerBgVariant: { default: null },
    headerBorderVariant: { default: null },
    headerClass: { default: void 0 },
    headerCloseClass: { default: void 0 },
    headerCloseLabel: { default: "Close" },
    headerCloseVariant: { default: "secondary" },
    headerTextVariant: { default: null },
    headerVariant: { default: null },
    noBackdrop: { type: Boolean, default: false },
    noFooter: { type: Boolean, default: false },
    noHeader: { type: Boolean, default: false },
    noHeaderClose: { type: Boolean, default: false },
    id: { default: void 0 },
    modalClass: { default: void 0 },
    noCloseOnBackdrop: { type: Boolean, default: false },
    noCloseOnEsc: { type: Boolean, default: false },
    noTrap: { type: Boolean, default: false },
    noStacking: { type: Boolean },
    okClass: { default: void 0 },
    okDisabled: { type: Boolean, default: false },
    okOnly: { type: Boolean, default: false },
    okTitle: { default: "OK" },
    okVariant: { default: "primary" },
    scrollable: { type: Boolean, default: false },
    size: { default: "md" },
    title: { default: void 0 },
    titleClass: { default: void 0 },
    titleVisuallyHidden: { type: Boolean, default: false },
    titleTag: { default: "h5" },
    teleportDisabled: { type: Boolean, default: false },
    teleportTo: { default: "body" },
    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(["backdrop", "cancel", "close", "esc", "ok", "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, "BModal");
    const emit = __emit;
    const slots = useSlots();
    const computedId = useId(() => props.id, "modal");
    const modelValue = useModel(__props, "modelValue");
    const element = useTemplateRef("_element");
    const fallbackFocusElement = useTemplateRef("_fallbackFocusElement");
    const okButton = useTemplateRef("_okButton");
    const cancelButton = useTemplateRef("_cancelButton");
    const closeButton = useTemplateRef("_closeButton");
    const pickFocusItem = () => {
      if (props.focus && typeof props.focus !== "boolean") {
        if (props.focus === "ok") {
          return okButton;
        } else if (props.focus === "close") {
          return closeButton;
        } else if (props.focus === "cancel") {
          return cancelButton;
        }
        return getElement(props.focus, element.value ?? void 0) ?? element.value;
      }
      return element;
    };
    let activeElement = null;
    const onAfterEnter = () => {
      if (props.noTrap && props.focus !== false) {
        activeElement = document.activeElement;
        if (activeElement === element.value) {
          activeElement = null;
        }
        const el = unrefElement(pickFocusItem());
        if (!el) return;
        el?.focus();
        if (el.tagName && el.tagName.toLowerCase() === "input" && typeof el.select === "function") {
          el.select();
        }
      }
    };
    const onAfterLeave = () => {
      if (props.noTrap && props.focus !== false && activeElement) {
        activeElement?.focus();
        activeElement = null;
      }
    };
    const {
      showRef,
      renderRef,
      renderBackdropRef,
      hide,
      show,
      toggle,
      computedNoAnimation,
      transitionProps,
      backdropTransitionProps,
      isLeaving,
      isVisible,
      trapActive,
      contentShowing,
      backdropReady,
      backdropVisible
    } = useShowHide(modelValue, props, emit, element, computedId, {
      // addShowClass: false,
      transitionProps: {
        onAfterEnter,
        onAfterLeave
      }
    });
    const { needsFallback } = useActivatedFocusTrap({
      element,
      isActive: trapActive,
      noTrap: () => props.noTrap,
      fallbackFocus: {
        ref: fallbackFocusElement,
        classSelector: fallbackClassSelector
      },
      focus: () => props.focus === false ? false : unrefElement(pickFocusItem()) ?? void 0
      // () => (typeof focus === 'boolean' ? focus : (unrefElement(focus) ?? undefined)),
    });
    onKeyStroke(
      "Escape",
      () => {
        hide("esc");
      },
      { target: element }
    );
    useSafeScrollLock(showRef, () => props.bodyScrolling);
    const hasHeaderCloseSlot = computed(() => !isEmptySlot(slots["header-close"]));
    const modalDialogClasses = computed(() => [
      props.dialogClass,
      {
        "modal-fullscreen": props.fullscreen === true,
        [`modal-fullscreen-${props.fullscreen}-down`]: typeof props.fullscreen === "string",
        [`modal-${props.size}`]: props.size !== "md",
        "modal-dialog-centered": props.centered,
        "modal-dialog-scrollable": props.scrollable
      }
    ]);
    const bodyColorClasses = useColorVariantClasses(() => ({
      bgVariant: props.bodyBgVariant,
      textVariant: props.bodyTextVariant,
      variant: props.bodyVariant
    }));
    const bodyClasses = computed(() => [props.bodyClass, bodyColorClasses.value]);
    const headerColorClasses = useColorVariantClasses(() => ({
      bgVariant: props.headerBgVariant,
      textVariant: props.headerTextVariant,
      variant: props.headerVariant,
      borderVariant: props.headerBorderVariant
    }));
    const headerClasses = computed(() => [props.headerClass, headerColorClasses.value]);
    const headerCloseAttrs = computed(() => ({
      variant: hasHeaderCloseSlot.value ? props.headerCloseVariant : void 0,
      class: props.headerCloseClass
    }));
    const footerColorClasses = useColorVariantClasses(() => ({
      bgVariant: props.footerBgVariant,
      textVariant: props.footerTextVariant,
      variant: props.footerVariant,
      borderVariant: props.footerBorderVariant
    }));
    const footerClasses = computed(() => [props.footerClass, footerColorClasses.value]);
    const titleClasses = computed(() => [
      props.titleClass,
      {
        ["visually-hidden"]: props.titleVisuallyHidden
      }
    ]);
    const disableCancel = computed(() => props.cancelDisabled || props.busy);
    const disableOk = computed(() => props.okDisabled || props.busy);
    const { activePosition, activeModalCount, stackWithoutSelf } = useModalManager(
      showRef,
      modelValue.value
    );
    const sharedClasses = computed(() => ({
      [`stack-position-${activePosition?.value ?? 0}`]: true,
      [`stack-inverse-position-${(activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0)}`]: true
    }));
    watch(stackWithoutSelf, (newValue, oldValue) => {
      if (newValue.length > oldValue.length && showRef.value === true && props.noStacking === true)
        hide();
    });
    const defaultModalDialogZIndex = ref(
      getModalZIndex(element.value ?? (typeof document !== "undefined" ? document.body : void 0))
    );
    onMounted(() => {
      watch(
        renderRef,
        (v) => {
          if (!v) return;
          nextTick(() => {
            if (!element.value) return;
            defaultModalDialogZIndex.value = getModalZIndex(element.value);
          });
        },
        { immediate: true }
      );
    });
    const computedZIndexNumber = computed(
      () => (
        // Make sure that newly opened modals have a higher z-index than currently active ones.
        // All active modals have a z-index of ('defaultZIndex' - 'stackSize' - 'positionInStack').
        //
        // This means inactive modals will already be higher than active ones when opened.
        showRef.value || isLeaving.value ? (
          // Just for reference there is a single frame in which the modal is not active but still has a higher z-index than the active ones due to _when_ it calculates its position. It's a small visual effect
          defaultModalDialogZIndex.value - ((activeModalCount?.value ?? 0) * 2 - (activePosition?.value ?? 0) * 2)
        ) : defaultModalDialogZIndex.value
      )
    );
    const computedZIndex = computed(() => ({
      "z-index": computedZIndexNumber.value,
      "--b-position": activePosition?.value ?? 0,
      "--b-inverse-position": (activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0),
      "--b-count": activeModalCount?.value ?? 0
    }));
    const computedZIndexBackdrop = computed(() => ({
      "z-index": computedZIndexNumber.value - 1,
      "--b-position": activePosition?.value ?? 0,
      "--b-inverse-position": (activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0),
      "--b-count": activeModalCount?.value ?? 0
    }));
    const sharedSlots = computed(() => ({
      id: computedId.value,
      cancel: () => {
        hide("cancel");
      },
      close: () => {
        hide("close");
      },
      hide,
      show,
      toggle,
      ok: () => {
        hide("ok");
      },
      active: showRef.value,
      visible: showRef.value
    }));
    __expose({
      hide,
      id: computedId,
      show,
      toggle,
      visible: showRef
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$1, {
        to: unref(props).teleportTo,
        disabled: 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("div", mergeProps({
                id: unref(computedId),
                ref: "_element",
                class: ["modal", [
                  unref(props).modalClass,
                  {
                    fade: !unref(computedNoAnimation),
                    show: unref(isVisible),
                    ...sharedClasses.value
                  }
                ]],
                role: "dialog",
                "aria-labelledby": !unref(props).noHeader ? `${unref(computedId)}-label` : void 0,
                "aria-describedby": `${unref(computedId)}-body`,
                tabindex: "-1"
              }, _ctx.$attrs, {
                style: [computedZIndex.value, { "display": "block" }],
                onMousedown: _cache[4] || (_cache[4] = withModifiers(($event) => unref(hide)("backdrop"), ["left", "self"]))
              }), [
                createElementVNode("div", {
                  class: normalizeClass(["modal-dialog", modalDialogClasses.value])
                }, [
                  unref(contentShowing) ? (openBlock(), createElementBlock("div", {
                    key: 0,
                    class: normalizeClass(["modal-content", unref(props).contentClass])
                  }, [
                    !unref(props).noHeader ? (openBlock(), createElementBlock("div", mergeProps({
                      key: 0,
                      class: ["modal-header", headerClasses.value]
                    }, unref(props).headerAttrs), [
                      renderSlot(_ctx.$slots, "header", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                        (openBlock(), createBlock(resolveDynamicComponent(unref(props).titleTag), {
                          id: `${unref(computedId)}-label`,
                          class: normalizeClass(["modal-title", titleClasses.value])
                        }, {
                          default: withCtx(() => [
                            renderSlot(_ctx.$slots, "title", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                              createTextVNode(toDisplayString(unref(props).title), 1)
                            ])
                          ]),
                          _: 3
                        }, 8, ["id", "class"])),
                        !unref(props).noHeaderClose ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
                          hasHeaderCloseSlot.value ? (openBlock(), createBlock(_sfc_main$2, mergeProps({
                            key: 0,
                            ref: "_closeButton"
                          }, headerCloseAttrs.value, {
                            onClick: _cache[0] || (_cache[0] = ($event) => unref(hide)("close"))
                          }), {
                            default: withCtx(() => [
                              renderSlot(_ctx.$slots, "header-close", normalizeProps(guardReactiveProps(sharedSlots.value)))
                            ]),
                            _: 3
                          }, 16)) : (openBlock(), createBlock(_sfc_main$3, mergeProps({
                            key: 1,
                            ref: "_closeButton",
                            "aria-label": unref(props).headerCloseLabel
                          }, headerCloseAttrs.value, {
                            onClick: _cache[1] || (_cache[1] = ($event) => unref(hide)("close"))
                          }), null, 16, ["aria-label"]))
                        ], 64)) : createCommentVNode("", true)
                      ])
                    ], 16)) : createCommentVNode("", true),
                    createElementVNode("div", mergeProps({
                      id: `${unref(computedId)}-body`,
                      class: ["modal-body", bodyClasses.value]
                    }, unref(props).bodyAttrs), [
                      renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                        createTextVNode(toDisplayString(unref(props).body), 1)
                      ])
                    ], 16, _hoisted_2),
                    !unref(props).noFooter ? (openBlock(), createElementBlock("div", {
                      key: 1,
                      class: normalizeClass(["modal-footer", footerClasses.value])
                    }, [
                      renderSlot(_ctx.$slots, "footer", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                        renderSlot(_ctx.$slots, "cancel", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                          !unref(props).okOnly ? (openBlock(), createBlock(_sfc_main$2, {
                            key: 0,
                            ref: "_cancelButton",
                            disabled: disableCancel.value,
                            size: unref(props).buttonSize,
                            variant: unref(props).cancelVariant,
                            class: normalizeClass(unref(props).cancelClass),
                            onClick: _cache[2] || (_cache[2] = ($event) => unref(hide)("cancel"))
                          }, {
                            default: withCtx(() => [
                              createTextVNode(toDisplayString(unref(props).cancelTitle), 1)
                            ]),
                            _: 1
                          }, 8, ["disabled", "size", "variant", "class"])) : createCommentVNode("", true)
                        ]),
                        renderSlot(_ctx.$slots, "ok", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                          createVNode(_sfc_main$2, {
                            ref: "_okButton",
                            disabled: disableOk.value,
                            size: unref(props).buttonSize,
                            variant: unref(props).okVariant,
                            class: normalizeClass(unref(props).okClass),
                            onClick: _cache[3] || (_cache[3] = ($event) => unref(hide)("ok"))
                          }, {
                            default: withCtx(() => [
                              createTextVNode(toDisplayString(unref(props).okTitle), 1)
                            ]),
                            _: 1
                          }, 8, ["disabled", "size", "variant", "class"])
                        ])
                      ])
                    ], 2)) : createCommentVNode("", true)
                  ], 2)) : createCommentVNode("", true)
                ], 2),
                unref(needsFallback) ? (openBlock(), createElementBlock("div", {
                  key: 0,
                  ref: "_fallbackFocusElement",
                  class: normalizeClass(fallbackClassSelector),
                  tabindex: "0",
                  style: { "width": "0", "height": "0", "overflow": "hidden" }
                }, null, 512)) : createCommentVNode("", true)
              ], 16, _hoisted_1), [
                [vShow, unref(showRef) && (unref(backdropReady) && unref(props).backdropFirst || !unref(props).backdropFirst)]
              ])
            ]),
            _: 3
          }, 16, ["appear"])) : createCommentVNode("", true),
          !unref(props).noBackdrop ? renderSlot(_ctx.$slots, "backdrop", normalizeProps(mergeProps({ key: 1 }, sharedSlots.value)), () => [
            unref(renderBackdropRef) ? (openBlock(), createBlock(Transition, normalizeProps(mergeProps({ key: 0 }, unref(backdropTransitionProps))), {
              default: withCtx(() => [
                withDirectives(createElementVNode("div", {
                  class: normalizeClass(["modal-backdrop", {
                    fade: !unref(computedNoAnimation),
                    show: unref(backdropVisible) || unref(computedNoAnimation),
                    ...sharedClasses.value
                  }]),
                  style: normalizeStyle(computedZIndexBackdrop.value),
                  onClick: _cache[5] || (_cache[5] = ($event) => unref(hide)("backdrop"))
                }, null, 6), [
                  [vShow, unref(showRef) || unref(isLeaving) && unref(props).backdropFirst && !unref(computedNoAnimation)]
                ])
              ]),
              _: 1
            }, 16)) : createCommentVNode("", true)
          ]) : createCommentVNode("", true)
        ]),
        _: 3
      }, 8, ["to", "disabled"]);
    };
  }
});
export {
  _sfc_main as _,
  useSharedModalStack as u
};
//# sourceMappingURL=BModal.vue_vue_type_script_setup_true_lang-SIs6PFOZ.mjs.map
