import { defineComponent, mergeModels, useSlots, useAttrs, useModel, inject, ref, computed, useTemplateRef, onUnmounted, watch, createBlock, openBlock, resolveDynamicComponent, unref, mergeProps, withCtx, renderSlot, createCommentVNode, nextTick, onMounted, provide, toRef, normalizeClass, createVNode, createElementVNode, createElementBlock, Fragment, renderList, withModifiers, withKeys, createTextVNode, toDisplayString } from "vue";
import { B as BvEvent } from "./classes-BW_GpXTu.mjs";
import { u as useAlignment } from "./useAlignment-Cw-9AVid.mjs";
import { u as useId } from "./useId-9_HUwM96.mjs";
import { l as createReusableTemplate } from "./index-nMtnPEP0.mjs";
import { t as tabsInjectionKey } from "./keys-D5Pj1dmf.mjs";
import { u as useDefaults } from "./useDefaults-DvqfKEoD.mjs";
import { s as sortSlotElementsByPosition } from "./dom-DVb-f0ZG.mjs";
import { f as flattenFragments } from "./flattenFragments-BoFLyuna.mjs";
const _sfc_main$1 = /* @__PURE__ */ defineComponent({
  ...{
    inheritAttrs: false
  },
  __name: "BTab",
  props: /* @__PURE__ */ mergeModels({
    buttonId: { default: void 0 },
    disabled: { type: Boolean, default: false },
    id: { default: void 0 },
    lazy: { type: Boolean, default: void 0 },
    unmountLazy: { type: Boolean, default: void 0 },
    noBody: { type: Boolean, default: false },
    tag: { default: "div" },
    title: { default: void 0 },
    titleItemClass: { default: void 0 },
    titleLinkAttrs: { default: void 0 },
    titleLinkClass: { default: void 0 }
  }, {
    "active": { type: Boolean, ...{
      default: false
    } },
    "activeModifiers": {}
  }),
  emits: ["update:active"],
  setup(__props, { expose: __expose }) {
    const _props = __props;
    const props = useDefaults(_props, "BTab");
    const slots = useSlots();
    const attrs = useAttrs();
    const activeModel = useModel(__props, "active");
    const parentData = inject(tabsInjectionKey, null);
    const localId = ref(props.id);
    const internalId = useId("", "tabpane");
    const computedId = computed(() => props.id ?? localId.value ?? internalId.value);
    const computedButtonId = useId(() => props.buttonId, "tab");
    const lazyRenderCompleted = ref(false);
    const el = useTemplateRef("_el");
    const processedAttrs = computed(() => {
      const { onClick: _, ...tabAttrs } = attrs;
      return tabAttrs;
    });
    function updateTab() {
      if (!parentData) return;
      const newId = parentData.registerTab(
        computed(
          () => ({
            internalId: internalId.value,
            id: computedId.value,
            active: activeModel.value,
            buttonId: computedButtonId.value,
            disabled: props.disabled,
            title: props.title,
            titleComponent: slots.title,
            titleItemClass: props.titleItemClass,
            titleLinkAttrs: props.titleLinkAttrs,
            titleLinkClass: props.titleLinkClass,
            onClick: attrs.onClick,
            el
          })
        )
      );
      if (newId !== localId.value) {
        localId.value = newId;
      }
    }
    if (parentData) {
      updateTab();
      if (activeModel.value) {
        parentData.activateTab(internalId.value);
      }
    }
    onUnmounted(() => {
      if (!parentData) return;
      parentData.unregisterTab(internalId.value);
    });
    const isActive = computed(() => parentData?.activeId.value === computedId.value);
    const show = ref(isActive.value);
    const computedLazy = computed(() => !!(parentData?.lazy.value || props.lazy));
    const computedActive = computed(() => isActive.value && !props.disabled);
    const showSlot = computed(
      () => computedActive.value || !computedLazy.value || computedLazy.value && !props.unmountLazy && lazyRenderCompleted.value
    );
    watch(showSlot, (shown) => {
      if (shown && !lazyRenderCompleted.value) lazyRenderCompleted.value = true;
    });
    watch(isActive, (active) => {
      if (active) {
        activeModel.value = true;
        setTimeout(() => {
          show.value = true;
        }, 0);
        return;
      }
      show.value = false;
      activeModel.value = false;
    });
    watch(activeModel, (active) => {
      if (props.disabled) {
        activeModel.value = false;
        return;
      }
      if (!parentData) return;
      if (!active) {
        if (isActive.value) {
          parentData.activateTab(void 0);
        }
        return;
      }
      if (!isActive.value) {
        parentData.activateTab(internalId.value);
      }
    });
    const computedClasses = computed(() => [
      {
        "active": isActive.value,
        "show": show.value,
        "card-body": parentData?.card.value && props.noBody === false,
        "fade": !parentData?.noFade.value
      },
      show.value ? parentData?.activeTabClass.value : parentData?.inactiveTabClass.value,
      parentData?.tabClass.value
    ]);
    __expose({
      activate: () => {
        activeModel.value = true;
      },
      deactivate: () => {
        activeModel.value = false;
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(resolveDynamicComponent(unref(props).tag), mergeProps({
        id: computedId.value,
        ref: "_el",
        class: ["tab-pane", computedClasses.value],
        role: "tabpanel",
        "aria-labelledby": unref(computedButtonId)
      }, processedAttrs.value), {
        default: withCtx(() => [
          showSlot.value ? renderSlot(_ctx.$slots, "default", { key: 0 }) : createCommentVNode("", true)
        ]),
        _: 3
      }, 16, ["id", "class", "aria-labelledby"]);
    };
  }
});
const _hoisted_1 = ["aria-orientation"];
const _hoisted_2 = ["id", "aria-controls", "aria-selected", "disabled", "tabindex", "onClick"];
const _sfc_main = /* @__PURE__ */ defineComponent({
  __name: "BTabs",
  props: /* @__PURE__ */ mergeModels({
    activeNavItemClass: { default: void 0 },
    activeTabClass: { default: void 0 },
    align: { default: void 0 },
    card: { type: Boolean, default: false },
    contentClass: { default: void 0 },
    end: { type: Boolean, default: false },
    fill: { type: Boolean, default: false },
    id: { default: void 0 },
    index: {},
    inactiveNavItemClass: { default: void 0 },
    inactiveTabClass: { default: void 0 },
    justified: { type: Boolean, default: false },
    lazy: { type: Boolean, default: false },
    navClass: { default: void 0 },
    navItemClass: { default: void 0 },
    navWrapperClass: { default: void 0 },
    noFade: { type: Boolean, default: false },
    noKeyNav: { type: Boolean, default: false },
    noNavStyle: { type: Boolean, default: false },
    pills: { type: Boolean, default: false },
    small: { type: Boolean, default: false },
    tag: { default: "div" },
    tabClass: { default: void 0 },
    underline: { type: Boolean, default: false },
    vertical: { type: Boolean, default: false }
  }, {
    "index": {
      default: -1
    },
    "indexModifiers": {},
    "modelValue": {
      default: void 0
    },
    "modelModifiers": {}
  }),
  emits: /* @__PURE__ */ mergeModels(["activate-tab"], ["update:index", "update:modelValue"]),
  setup(__props, { emit: __emit }) {
    const _props = __props;
    const props = useDefaults(_props, "BTabs");
    const emit = __emit;
    const slots = useSlots();
    const activeIndex = useModel(__props, "index");
    const activeId = useModel(__props, "modelValue");
    const ReusableEmptyTab = createReusableTemplate();
    const tabsInternal = ref([]);
    const tabElementsArray = ref([]);
    const isChildActive = ref(false);
    const initialIds = ref([]);
    const hasExplicitIds = ref(false);
    const updateTabElementsArray = () => {
      const tabElements = flattenFragments(slots.default?.({}) ?? []);
      tabElementsArray.value = (Array.isArray(tabElements) ? tabElements : [tabElements]).filter(
        (tab) => tab.type === _sfc_main$1
      );
      if (initialIds.value.length === 0) {
        initialIds.value = tabElementsArray.value.map(
          (tab) => unref(useId(() => tab.props?.id, "tabpane"))
        );
        hasExplicitIds.value = tabElementsArray.value.some((tab) => tab.props?.id !== void 0);
      }
      isChildActive.value = tabElementsArray.value.some(
        (tab) => tab.props?.active !== void 0 && tab.props?.active !== false
      );
    };
    updateTabElementsArray();
    watch(
      () => slots.default?.({}),
      () => {
        updateTabElementsArray();
        nextTick(() => {
          sortTabs();
        });
      }
    );
    const tabs = computed(() => {
      if (tabsInternal.value.length === 0) {
        const _activeIndex = tabElementsArray.value.findIndex(
          (tab) => tab.props?.active !== void 0 && (tab.props.disabled === false || tab.props.disabled === void 0) || activeId.value && tab.props?.id === activeId.value
        );
        return tabElementsArray.value.map((tab, index) => {
          const active = _activeIndex !== -1 ? index === _activeIndex : activeIndex.value > -1 ? index === activeIndex.value : index === 0;
          return {
            id: tab.props?.id ?? initialIds.value[index],
            internalId: `premount-${index}`,
            // temporary id for the tab
            buttonId: tab.props?.buttonId,
            disabled: tab.props?.disabled,
            title: tab.props?.title,
            titleComponent: tab.children?.title,
            titleItemClass: tab.props?.titleItemClass,
            titleLinkAttrs: tab.props?.titleLinkAttrs,
            titleLinkClass: tab.props?.titleLinkClass,
            onClick: tab.props?.onClick,
            active,
            navItemClasses: [
              {
                active,
                disabled: !(tab.props?.disabled === false || tab.props?.disabled === void 0)
              },
              active ? props.activeNavItemClass : props.inactiveNavItemClass,
              props.navItemClass
            ]
          };
        });
      }
      return tabsInternal.value.map((_tab) => {
        const tab = unref(_tab);
        const active = tab.id === activeId.value;
        return {
          ...tab,
          active,
          navItemClasses: [
            {
              active,
              disabled: tab.disabled
            },
            active ? props.activeNavItemClass : props.inactiveNavItemClass,
            props.navItemClass
          ]
        };
      });
    });
    let initialized = false;
    let updateInitialActiveIndex = false;
    let updateInitialActiveId = false;
    let delayedTabSelection = false;
    const needsDelayedSelection = activeIndex.value > -1 && !activeId.value && !hasExplicitIds.value && tabElementsArray.value.length > 0;
    if (needsDelayedSelection) {
      delayedTabSelection = true;
      updateInitialActiveId = true;
    } else if (activeIndex.value === -1 && activeId.value) {
      if (tabs.value.findIndex((t) => t.id === activeId.value) !== -1) {
        activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value);
      } else {
        updateInitialActiveIndex = true;
      }
    } else if (activeIndex.value > -1 && !activeId.value) {
      if (tabs.value[activeIndex.value]?.id) {
        activeId.value = tabs.value[activeIndex.value]?.id;
      } else {
        updateInitialActiveId = true;
      }
    } else if (activeIndex.value === -1 && !activeId.value && !isChildActive.value) {
      activeIndex.value = tabs.value.findIndex((t) => t.disabled === void 0 || t.disabled === false);
      activeId.value = tabs.value[activeIndex.value]?.id;
    } else if (activeIndex.value === -1 && !activeId.value && isChildActive.value) {
      activeIndex.value = tabs.value.findIndex(
        (t) => t.active !== void 0 && t.active !== false && (t.disabled === void 0 || t.disabled === false)
      );
      activeId.value = tabs.value[activeIndex.value]?.id;
    }
    function updateInitialIndexAndId() {
      if (updateInitialActiveIndex) {
        const index = tabs.value.findIndex((t) => t.id === activeId.value);
        if (index !== -1) {
          nextTick(() => {
            activeIndex.value = index;
            updateInitialActiveIndex = false;
          });
        }
      }
      if (updateInitialActiveId) {
        if (delayedTabSelection && tabsInternal.value.length === 0) {
          return;
        }
        if (activeIndex.value > -1 && tabs.value[activeIndex.value]?.id) {
          nextTick(() => {
            activeId.value = tabs.value[activeIndex.value]?.id;
            updateInitialActiveId = false;
            delayedTabSelection = false;
          });
        }
      }
    }
    updateInitialIndexAndId();
    const showEmpty = computed(() => !(tabs?.value && tabs.value.length > 0));
    const computedClasses = computed(() => ({
      "d-flex": props.vertical,
      "align-items-start": props.vertical
    }));
    const alignment = useAlignment(() => props.align);
    const navTabsClasses = computed(() => ({
      "nav-pills": props.pills,
      "nav-underline": props.underline,
      "flex-column me-3": props.vertical,
      [alignment.value]: props.align !== void 0,
      "nav-fill": props.fill,
      "card-header-tabs": props.card && !props.pills && !props.underline,
      "card-header-pills": props.card && props.pills,
      "nav-justified": props.justified,
      "nav-tabs": !props.noNavStyle && !props.pills && !props.underline,
      "small": props.small
    }));
    const handleClick = (event, index) => {
      if (index >= 0 && !tabs.value[index].disabled && tabs.value[index]?.onClick && typeof tabs.value[index].onClick === "function") {
        tabs.value[index].onClick?.(event);
        if (event.defaultPrevented) {
          document.getElementById(tabs.value[index].buttonId)?.blur();
          return;
        }
      }
      activeIndex.value = index;
    };
    const keynav = (e, direction) => {
      if (tabs.value.length <= 0 || props.noKeyNav) return;
      e.preventDefault();
      e.stopPropagation();
      activeIndex.value = nextIndex(activeIndex.value + direction, direction);
      nextTick(() => {
        if (activeIndex.value >= 0) {
          document.getElementById(tabs.value[activeIndex.value]?.buttonId)?.focus();
        }
      });
    };
    const nextIndex = (start, direction) => {
      let index = start;
      let minIdx = -1;
      let maxIdx = -1;
      for (let i = 0; i < tabs.value.length; i++) {
        if (!tabs.value[i].disabled) {
          if (minIdx === -1) minIdx = i;
          maxIdx = i;
        }
      }
      while (index >= minIdx && index <= maxIdx && tabs.value[index].disabled) {
        index += direction;
      }
      if (index < minIdx) index = minIdx;
      if (index > maxIdx) index = maxIdx;
      return index;
    };
    let previousIndex;
    let isReverting = false;
    watch(activeIndex, (newValue, oldValue) => {
      if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {
        return;
      }
      if (isReverting) {
        isReverting = false;
        return;
      }
      const index = nextIndex(newValue, newValue > oldValue ? 1 : -1);
      if (index !== newValue) {
        previousIndex = oldValue;
        activeIndex.value = index;
        return;
      }
      const tabEvent = new BvEvent("activate-tab", { cancelable: true });
      emit("activate-tab", {
        newTabId: tabs.value[index]?.id,
        prevTabId: tabs.value[previousIndex ?? oldValue]?.id,
        newTabIndex: index,
        prevTabIndex: previousIndex ?? oldValue,
        event: tabEvent
      });
      if (tabEvent.defaultPrevented) {
        isReverting = true;
        const prev = previousIndex ?? oldValue ?? nextIndex(0, 1);
        previousIndex = void 0;
        if (activeId.value !== tabs.value[prev]?.id) {
          activeId.value = tabs.value[prev]?.id;
        }
        nextTick(() => {
          if (prev >= 0) {
            document.getElementById(tabs.value[prev]?.buttonId)?.focus();
          }
        });
        return;
      }
      if (activeId.value !== tabs.value[index]?.id) {
        activeId.value = tabs.value[index]?.id;
      }
      previousIndex = void 0;
    });
    watch(activeId, (newValue, oldValue) => {
      if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {
        return;
      }
      const index = tabs.value.findIndex((t) => t.id === newValue);
      if (index === activeIndex.value) return;
      const oldIndex = tabs.value.findIndex((t) => t.id === oldValue);
      if (tabs.value[index]?.disabled) {
        activeIndex.value = nextIndex(index, index > oldIndex ? 1 : -1);
        return;
      }
      if (index === -1) {
        activeIndex.value = nextIndex(0, 1);
        nextTick(() => {
          activeId.value = tabs.value[activeIndex.value]?.id;
        });
        return;
      }
      activeIndex.value = index;
    });
    const registerTab = (tab) => {
      const idx = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId);
      if (idx === -1) {
        tabsInternal.value.push(tab);
        if (initialized) {
          nextTick(() => {
            sortTabs();
          });
        } else {
          if (delayedTabSelection) {
            nextTick(() => {
              updateInitialIndexAndId();
            });
          }
        }
      } else {
        tabsInternal.value[idx] = tab;
        if (initialized) {
          sortTabs();
        }
      }
      const idx2 = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId);
      return tab.value.id ?? (!initialized ? initialIds.value[idx2] : tab.value.internalId);
    };
    onMounted(() => {
      updateInitialIndexAndId();
      sortTabs();
      initialized = true;
    });
    const sortTabs = () => {
      tabsInternal.value.sort((a, b) => sortSlotElementsByPosition(a.value.el.value, b.value.el.value));
      if (activeId.value && activeIndex.value !== tabs.value.findIndex((t) => t.id === activeId.value)) {
        activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value);
      }
    };
    const unregisterTab = (id) => {
      tabsInternal.value = tabsInternal.value.filter((t) => t.value.internalId !== id);
    };
    provide(tabsInjectionKey, {
      lazy: toRef(() => props.lazy),
      card: toRef(() => props.card),
      noFade: toRef(() => props.noFade),
      activeTabClass: toRef(() => props.activeTabClass),
      inactiveTabClass: toRef(() => props.inactiveTabClass),
      tabClass: toRef(() => props.tabClass),
      registerTab,
      unregisterTab,
      activeId,
      activateTab: (internalId) => {
        const idx = tabs.value.findIndex((t) => t.internalId === internalId);
        if (internalId === void 0 || idx === -1) {
          activeIndex.value = nextIndex(0, 1);
          return;
        }
        activeIndex.value = idx;
      }
    });
    return (_ctx, _cache) => {
      return openBlock(), createBlock(resolveDynamicComponent(unref(props).tag), {
        id: unref(props).id,
        class: normalizeClass(["tabs", computedClasses.value])
      }, {
        default: withCtx(() => [
          createVNode(unref(ReusableEmptyTab).define, null, {
            default: withCtx(() => [
              createElementVNode("div", {
                class: normalizeClass(["tab-content", unref(props).contentClass])
              }, [
                renderSlot(_ctx.$slots, "default"),
                showEmpty.value ? (openBlock(), createElementBlock("div", {
                  key: "bv-empty-tab",
                  class: normalizeClass(["tab-pane active", { "card-body": unref(props).card }])
                }, [
                  renderSlot(_ctx.$slots, "empty")
                ], 2)) : createCommentVNode("", true)
              ], 2)
            ]),
            _: 3
          }),
          unref(props).end ? (openBlock(), createBlock(unref(ReusableEmptyTab).reuse, { key: 0 })) : createCommentVNode("", true),
          createElementVNode("div", {
            class: normalizeClass([
              unref(props).navWrapperClass,
              { "card-header": unref(props).card, "ms-auto": __props.vertical && unref(props).end }
            ])
          }, [
            createElementVNode("ul", {
              class: normalizeClass(["nav", [navTabsClasses.value, unref(props).navClass]]),
              role: "tablist",
              "aria-orientation": unref(props).vertical ? "vertical" : "horizontal"
            }, [
              renderSlot(_ctx.$slots, "tabs-start"),
              (openBlock(true), createElementBlock(Fragment, null, renderList(tabs.value, (tab, idx) => {
                return openBlock(), createElementBlock("li", {
                  key: tab.id ?? tab.internalId,
                  class: normalizeClass(["nav-item", tab.titleItemClass]),
                  role: "presentation"
                }, [
                  createElementVNode("button", mergeProps({
                    id: tab.buttonId,
                    class: ["nav-link", [tab.navItemClasses, tab.titleLinkClass]],
                    role: "tab",
                    "aria-controls": tab.id,
                    "aria-selected": tab.active,
                    disabled: tab.disabled,
                    tabindex: unref(props).noKeyNav ? void 0 : tab.active ? void 0 : -1,
                    type: "button"
                  }, { ref_for: true }, tab.titleLinkAttrs, {
                    onKeydown: [
                      _cache[0] || (_cache[0] = withKeys(withModifiers(($event) => !unref(props).vertical && keynav($event, -1), ["exact"]), ["left"])),
                      _cache[1] || (_cache[1] = withKeys(withModifiers(($event) => !unref(props).vertical && keynav($event, -999), ["shift"]), ["left"])),
                      _cache[2] || (_cache[2] = withKeys(withModifiers(($event) => unref(props).vertical && keynav($event, -1), ["exact"]), ["up"])),
                      _cache[3] || (_cache[3] = withKeys(withModifiers(($event) => unref(props).vertical && keynav($event, -999), ["shift"]), ["up"])),
                      _cache[4] || (_cache[4] = withKeys(withModifiers(($event) => !unref(props).vertical && keynav($event, 1), ["exact"]), ["right"])),
                      _cache[5] || (_cache[5] = withKeys(withModifiers(($event) => !unref(props).vertical && keynav($event, 999), ["shift"]), ["right"])),
                      _cache[6] || (_cache[6] = withKeys(withModifiers(($event) => unref(props).vertical && keynav($event, 1), ["exact"]), ["down"])),
                      _cache[7] || (_cache[7] = withKeys(withModifiers(($event) => unref(props).vertical && keynav($event, 999), ["shift"]), ["down"])),
                      _cache[8] || (_cache[8] = withKeys(($event) => keynav($event, -999), ["page-up"])),
                      _cache[9] || (_cache[9] = withKeys(($event) => keynav($event, 999), ["page-down"])),
                      _cache[10] || (_cache[10] = withKeys(($event) => keynav($event, -999), ["home"])),
                      _cache[11] || (_cache[11] = withKeys(($event) => keynav($event, 999), ["end"]))
                    ],
                    onClick: withModifiers((e) => handleClick(e, idx), ["stop"])
                  }), [
                    tab.titleComponent ? (openBlock(), createBlock(resolveDynamicComponent(tab.titleComponent), { key: 0 })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
                      createTextVNode(toDisplayString(tab.title), 1)
                    ], 64))
                  ], 16, _hoisted_2)
                ], 2);
              }), 128)),
              renderSlot(_ctx.$slots, "tabs-end")
            ], 10, _hoisted_1)
          ], 2),
          !unref(props).end ? (openBlock(), createBlock(unref(ReusableEmptyTab).reuse, { key: 1 })) : createCommentVNode("", true)
        ]),
        _: 3
      }, 8, ["id", "class"]);
    };
  }
});
export {
  _sfc_main$1 as _,
  _sfc_main as a
};
//# sourceMappingURL=BTabs.vue_vue_type_script_setup_true_lang-BkNgaT2C.mjs.map
