import { defineComponent, mergeModels, useSlots, useModel, useTemplateRef, ref, onMounted, computed, watch, createBlock, openBlock, unref, withCtx, createCommentVNode, renderSlot, Transition, mergeProps, withDirectives, createElementVNode, createElementBlock, Fragment, normalizeProps, guardReactiveProps, createTextVNode, toDisplayString, normalizeClass, vShow, nextTick } from "vue";
import { d as useBreakpoints, o as onKeyStroke, e as unrefElement, f as breakpointsBootstrapV5 } from "./index-nMtnPEP0.mjs";
import { u as useSafeScrollLock, a as useActivatedFocusTrap } from "./useSafeScrollLock-BMtL1rUG.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$3 } from "./BCloseButton.vue_vue_type_script_setup_true_lang-CezXiDAc.mjs";
import { _ as _sfc_main$1 } from "./ConditionalTeleport.vue_vue_type_script_lang-Cp-egLmm.mjs";
import { i as isEmptySlot } from "./dom-DVb-f0ZG.mjs";
import { u as useShowHide } from "./useShowHide-rIwHwrmD.mjs";
import { g as getElement } from "./getElement-DrDVR-jO.mjs";
const _hoisted_1 = ["id", "aria-labelledby"];
const _hoisted_2 = ["id"];
const fallbackClassSelector = "offcanvas-fallback-focus";
const _sfc_main = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "BOffcanvas",
  props: /* @__PURE__ */ mergeModels({
    noBackdrop: { type: Boolean, default: false },
    backdropFirst: { type: Boolean, default: false },
    bodyAttrs: { default: void 0 },
    bodyClass: { default: void 0 },
    bodyScrolling: { type: Boolean, default: false },
    focus: { type: [String, Boolean, Object, null], default: void 0 },
    footerClass: { default: void 0 },
    headerAttrs: { default: void 0 },
    headerClass: { default: void 0 },
    headerCloseClass: { default: void 0 },
    headerCloseLabel: { default: "Close" },
    headerCloseVariant: { default: "secondary" },
    id: { default: void 0 },
    noCloseOnBackdrop: { type: Boolean, default: false },
    noCloseOnEsc: { type: Boolean, default: false },
    noHeader: { type: Boolean, default: false },
    noTrap: { type: Boolean, default: false },
    noHeaderClose: { type: Boolean, default: false },
    placement: { default: "start" },
    shadow: { type: [String, Boolean], default: false },
    title: { default: void 0 },
    responsive: {},
    width: { default: void 0 },
    teleportDisabled: { type: Boolean, default: false },
    teleportTo: { default: "body" },
    initialAnimation: { type: Boolean, default: false },
    noAnimation: { type: Boolean, default: false },
    noFade: { type: Boolean },
    lazy: { type: Boolean, default: false },
    unmountLazy: { type: Boolean, default: false },
    show: { type: Boolean, default: false },
    transProps: {},
    visible: { type: Boolean, default: false }
  }, {
    "modelValue": { type: Boolean, ...{
      default: false
    } },
    "modelModifiers": {}
  }),
  emits: /* @__PURE__ */ mergeModels(["close", "esc", "backdrop", "breakpoint", "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, "BOffcanvas");
    const emit = __emit;
    const slots = useSlots();
    const modelValue = useModel(__props, "modelValue");
    const computedId = useId(() => props.id, "offcanvas");
    const element = useTemplateRef("_element");
    const fallbackFocusElement = useTemplateRef("_fallbackFocusElement");
    const closeButton = useTemplateRef("_close");
    const pickFocusItem = () => {
      if (props.focus && typeof props.focus !== "boolean") {
        if (props.focus === "close") {
          return closeButton;
        }
        return getElement(props.focus, element.value ?? void 0);
      }
      return element;
    };
    const onAfterEnter = () => {
      nextTick(() => {
        if (props.focus !== false && !isOpenByBreakpoint.value && props.noTrap) {
          const focusElement = unrefElement(pickFocusItem());
          focusElement?.focus();
        }
      });
    };
    const {
      showRef,
      renderRef,
      renderBackdropRef,
      hide,
      show,
      toggle,
      computedNoAnimation,
      contentShowing,
      transitionProps,
      backdropReady,
      backdropTransitionProps,
      backdropVisible,
      isVisible,
      buildTriggerableEvent,
      isLeaving,
      trapActive,
      setLocalNoAnimation
    } = useShowHide(modelValue, props, emit, element, computedId, {
      transitionProps: {
        onAfterEnter,
        enterToClass: "showing",
        leaveToClass: "hiding",
        enterActiveClass: "",
        leaveActiveClass: "",
        enterFromClass: "",
        leaveFromClass: ""
      }
    });
    const breakpoints = useBreakpoints(breakpointsBootstrapV5);
    const smallerOrEqualToBreakpoint = breakpoints.smallerOrEqual(() => props.responsive ?? "xs");
    const isOpenByBreakpoint = ref(false);
    onMounted(() => {
      if (props.responsive !== void 0) {
        isOpenByBreakpoint.value = !smallerOrEqualToBreakpoint.value;
        emit("breakpoint", buildTriggerableEvent("breakpoint"), isOpenByBreakpoint.value);
      }
    });
    useSafeScrollLock(showRef, () => props.bodyScrolling || isOpenByBreakpoint.value);
    onKeyStroke(
      "Escape",
      () => {
        hide("esc");
      },
      { target: element }
    );
    const { needsFallback } = useActivatedFocusTrap({
      element,
      isActive: trapActive,
      noTrap: () => props.noTrap || isOpenByBreakpoint.value,
      fallbackFocus: {
        classSelector: fallbackClassSelector,
        ref: fallbackFocusElement
      },
      focus: () => props.focus === false || isOpenByBreakpoint.value ? false : unrefElement(pickFocusItem()) ?? void 0
    });
    const showBackdrop = computed(
      () => (props.responsive === void 0 || !isOpenByBreakpoint.value) && props.noBackdrop === false && (showRef.value === true || isLeaving.value && props.backdropFirst && !computedNoAnimation.value)
    );
    const hasHeaderCloseSlot = computed(() => !isEmptySlot(slots["header-close"]));
    const headerCloseClasses = computed(() => [
      { "text-reset": !hasHeaderCloseSlot.value },
      props.headerCloseClass
    ]);
    const headerCloseAttrs = computed(() => ({
      variant: hasHeaderCloseSlot.value ? props.headerCloseVariant : void 0,
      class: headerCloseClasses.value
    }));
    const hasFooterSlot = computed(() => !isEmptySlot(slots.footer));
    const computedClasses = computed(() => [
      props.responsive === void 0 ? "offcanvas" : `offcanvas-${props.responsive}`,
      `offcanvas-${props.placement}`,
      {
        "show": isVisible.value,
        [`shadow-${props.shadow}`]: !!props.shadow,
        "no-transition": computedNoAnimation.value
      }
    ]);
    const computedStyles = computed(() => ({
      width: props.width
    }));
    const sharedSlots = computed(() => ({
      visible: isVisible.value,
      placement: props.placement,
      hide,
      show,
      toggle,
      id: computedId.value,
      active: trapActive.value
    }));
    watch(smallerOrEqualToBreakpoint, (newValue) => {
      if (props.responsive === void 0) return;
      if (newValue === true) {
        const opened = false;
        setLocalNoAnimation(true);
        requestAnimationFrame(() => {
          isOpenByBreakpoint.value = opened;
        });
        emit("breakpoint", buildTriggerableEvent("breakpoint"), opened);
        emit("hide", buildTriggerableEvent("hide"));
      } else {
        const opened = true;
        setLocalNoAnimation(true);
        requestAnimationFrame(() => {
          isOpenByBreakpoint.value = opened;
        });
        emit("breakpoint", buildTriggerableEvent("breakpoint"), opened);
        emit("show", buildTriggerableEvent("show"));
      }
    });
    __expose({
      hide,
      show,
      toggle,
      isOpenByBreakpoint
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(_sfc_main$1, {
        to: unref(props).teleportTo,
        disabled: unref(props).teleportDisabled || isOpenByBreakpoint.value
      }, {
        default: withCtx(() => [
          unref(renderRef) || unref(contentShowing) || isOpenByBreakpoint.value ? (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",
                "aria-modal": "true",
                role: "dialog",
                class: computedClasses.value,
                style: computedStyles.value,
                tabindex: "-1",
                "aria-labelledby": `${unref(computedId)}-offcanvas-label`,
                "data-bs-backdrop": "false"
              }, _ctx.$attrs), [
                unref(contentShowing) || isOpenByBreakpoint.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
                  !unref(props).noHeader ? (openBlock(), createElementBlock("div", mergeProps({
                    key: 0,
                    class: ["offcanvas-header", unref(props).headerClass]
                  }, unref(props).headerAttrs), [
                    renderSlot(_ctx.$slots, "header", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                      createElementVNode("h5", {
                        id: `${unref(computedId)}-offcanvas-label`,
                        class: "offcanvas-title"
                      }, [
                        renderSlot(_ctx.$slots, "title", normalizeProps(guardReactiveProps(sharedSlots.value)), () => [
                          createTextVNode(toDisplayString(unref(props).title), 1)
                        ])
                      ], 8, _hoisted_2),
                      !unref(props).noHeaderClose ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
                        hasHeaderCloseSlot.value ? (openBlock(), createBlock(_sfc_main$2, mergeProps({
                          key: 0,
                          ref: "_close"
                        }, 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: "_close",
                          "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({
                    class: ["offcanvas-body", unref(props).bodyClass]
                  }, unref(props).bodyAttrs), [
                    renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(sharedSlots.value)))
                  ], 16),
                  hasFooterSlot.value ? (openBlock(), createElementBlock("div", {
                    key: 1,
                    class: normalizeClass(unref(props).footerClass)
                  }, [
                    renderSlot(_ctx.$slots, "footer", normalizeProps(guardReactiveProps(sharedSlots.value)))
                  ], 2)) : createCommentVNode("", true)
                ], 64)) : createCommentVNode("", true),
                unref(needsFallback) ? (openBlock(), createElementBlock("div", {
                  key: 1,
                  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) || isOpenByBreakpoint.value
                ]
              ])
            ]),
            _: 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(["offcanvas-backdrop", {
                    fade: !unref(computedNoAnimation),
                    show: unref(backdropVisible) || unref(computedNoAnimation)
                  }]),
                  onClick: _cache[2] || (_cache[2] = ($event) => unref(hide)("backdrop"))
                }, null, 2), [
                  [vShow, showBackdrop.value]
                ])
              ]),
              _: 1
            }, 16)) : createCommentVNode("", true)
          ]) : createCommentVNode("", true)
        ]),
        _: 3
      }, 8, ["to", "disabled"]);
    };
  }
});
export {
  _sfc_main as _
};
//# sourceMappingURL=BOffcanvas.vue_vue_type_script_setup_true_lang-BDfsBBB8.mjs.map
