UNPKG

bootstrap-vue-next

Version:

Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development

1 lines 54.7 kB
{"version":3,"file":"BTabs-7IT0dhVr.mjs","names":[],"sources":["../src/components/BTabs/BTab.vue","../src/components/BTabs/BTab.vue","../src/components/BTabs/BTabs.vue","../src/components/BTabs/BTabs.vue"],"sourcesContent":["<template>\n <component\n :is=\"props.tag\"\n :id=\"computedId\"\n ref=\"_el\"\n class=\"tab-pane\"\n :class=\"computedClasses\"\n role=\"tabpanel\"\n :aria-labelledby=\"computedButtonId\"\n v-bind=\"processedAttrs\"\n >\n <slot v-if=\"showSlot\" />\n </component>\n</template>\n\n<script setup lang=\"ts\">\nimport {computed, inject, onUnmounted, ref, useAttrs, useTemplateRef, watch} from 'vue'\nimport {useId} from '../../composables/useId'\nimport {useDefaults} from '../../composables/useDefaults'\nimport type {TabType} from '../../types/Tab'\nimport type {BTabProps} from '../../types/ComponentProps'\nimport {tabsInjectionKey} from '../../utils/keys'\nimport type {BTabSlots} from '../../types/ComponentSlots'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst _props = withDefaults(defineProps<Omit<BTabProps, 'active'>>(), {\n buttonId: undefined,\n disabled: false,\n id: undefined,\n lazy: undefined,\n unmountLazy: undefined,\n noBody: false,\n tag: 'div',\n title: undefined,\n titleItemClass: undefined,\n titleLinkAttrs: undefined,\n titleLinkClass: undefined,\n})\nconst props = useDefaults(_props, 'BTab')\nconst slots = defineSlots<BTabSlots>()\nconst attrs = useAttrs()\n\nconst activeModel = defineModel<Exclude<BTabProps['active'], undefined>>('active', {\n default: false,\n})\n\nconst parentData = inject(tabsInjectionKey, null)\n\nconst localId = ref(props.id)\nconst internalId = useId('', 'tabpane')\nconst computedId = computed(() => props.id ?? localId.value ?? internalId.value)\nconst computedButtonId = useId(() => props.buttonId, 'tab')\n\nconst lazyRenderCompleted = ref(false)\nconst el = useTemplateRef('_el')\n\nconst processedAttrs = computed(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {onClick: _, ...tabAttrs} = attrs\n return tabAttrs\n})\n\nfunction updateTab() {\n if (!parentData) return\n const newId = parentData.registerTab(\n computed(\n () =>\n ({\n internalId: internalId.value,\n id: computedId.value,\n active: activeModel.value,\n buttonId: computedButtonId.value,\n disabled: props.disabled,\n title: props.title,\n titleComponent: slots.title,\n titleItemClass: props.titleItemClass,\n titleLinkAttrs: props.titleLinkAttrs,\n titleLinkClass: props.titleLinkClass,\n onClick: attrs.onClick,\n el,\n }) as TabType\n )\n )\n if (newId !== localId.value) {\n localId.value = newId\n }\n}\n\nif (parentData) {\n updateTab()\n if (activeModel.value) {\n parentData.activateTab(internalId.value)\n }\n}\n\nonUnmounted(() => {\n if (!parentData) return\n parentData.unregisterTab(internalId.value)\n})\n\nconst isActive = computed(() => parentData?.activeId.value === computedId.value)\nconst show = ref(isActive.value)\n\nconst computedLazy = computed(() => !!(parentData?.lazy.value || props.lazy))\n\nconst computedActive = computed(() => isActive.value && !props.disabled)\nconst showSlot = computed(\n () =>\n computedActive.value ||\n !computedLazy.value ||\n (computedLazy.value && !props.unmountLazy && lazyRenderCompleted.value)\n)\n\nwatch(showSlot, (shown) => {\n if (shown && !lazyRenderCompleted.value) lazyRenderCompleted.value = true\n})\n\nwatch(isActive, (active) => {\n if (active) {\n activeModel.value = true\n setTimeout(() => {\n show.value = true\n }, 0)\n return\n }\n show.value = false\n activeModel.value = false\n})\n\nwatch(activeModel, (active) => {\n if (props.disabled) {\n activeModel.value = false\n return\n }\n if (!parentData) return\n if (!active) {\n if (isActive.value) {\n parentData.activateTab(undefined)\n }\n return\n }\n if (!isActive.value) {\n parentData.activateTab(internalId.value)\n }\n})\n\nconst computedClasses = computed(() => [\n {\n 'active': isActive.value,\n 'show': show.value,\n 'card-body': parentData?.card.value && props.noBody === false,\n 'fade': !parentData?.noFade.value,\n },\n show.value ? parentData?.activeTabClass.value : parentData?.inactiveTabClass.value,\n parentData?.tabClass.value,\n])\n\ndefineExpose({\n activate: () => {\n activeModel.value = true\n },\n deactivate: () => {\n activeModel.value = false\n },\n})\n</script>\n","<template>\n <component\n :is=\"props.tag\"\n :id=\"computedId\"\n ref=\"_el\"\n class=\"tab-pane\"\n :class=\"computedClasses\"\n role=\"tabpanel\"\n :aria-labelledby=\"computedButtonId\"\n v-bind=\"processedAttrs\"\n >\n <slot v-if=\"showSlot\" />\n </component>\n</template>\n\n<script setup lang=\"ts\">\nimport {computed, inject, onUnmounted, ref, useAttrs, useTemplateRef, watch} from 'vue'\nimport {useId} from '../../composables/useId'\nimport {useDefaults} from '../../composables/useDefaults'\nimport type {TabType} from '../../types/Tab'\nimport type {BTabProps} from '../../types/ComponentProps'\nimport {tabsInjectionKey} from '../../utils/keys'\nimport type {BTabSlots} from '../../types/ComponentSlots'\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst _props = withDefaults(defineProps<Omit<BTabProps, 'active'>>(), {\n buttonId: undefined,\n disabled: false,\n id: undefined,\n lazy: undefined,\n unmountLazy: undefined,\n noBody: false,\n tag: 'div',\n title: undefined,\n titleItemClass: undefined,\n titleLinkAttrs: undefined,\n titleLinkClass: undefined,\n})\nconst props = useDefaults(_props, 'BTab')\nconst slots = defineSlots<BTabSlots>()\nconst attrs = useAttrs()\n\nconst activeModel = defineModel<Exclude<BTabProps['active'], undefined>>('active', {\n default: false,\n})\n\nconst parentData = inject(tabsInjectionKey, null)\n\nconst localId = ref(props.id)\nconst internalId = useId('', 'tabpane')\nconst computedId = computed(() => props.id ?? localId.value ?? internalId.value)\nconst computedButtonId = useId(() => props.buttonId, 'tab')\n\nconst lazyRenderCompleted = ref(false)\nconst el = useTemplateRef('_el')\n\nconst processedAttrs = computed(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {onClick: _, ...tabAttrs} = attrs\n return tabAttrs\n})\n\nfunction updateTab() {\n if (!parentData) return\n const newId = parentData.registerTab(\n computed(\n () =>\n ({\n internalId: internalId.value,\n id: computedId.value,\n active: activeModel.value,\n buttonId: computedButtonId.value,\n disabled: props.disabled,\n title: props.title,\n titleComponent: slots.title,\n titleItemClass: props.titleItemClass,\n titleLinkAttrs: props.titleLinkAttrs,\n titleLinkClass: props.titleLinkClass,\n onClick: attrs.onClick,\n el,\n }) as TabType\n )\n )\n if (newId !== localId.value) {\n localId.value = newId\n }\n}\n\nif (parentData) {\n updateTab()\n if (activeModel.value) {\n parentData.activateTab(internalId.value)\n }\n}\n\nonUnmounted(() => {\n if (!parentData) return\n parentData.unregisterTab(internalId.value)\n})\n\nconst isActive = computed(() => parentData?.activeId.value === computedId.value)\nconst show = ref(isActive.value)\n\nconst computedLazy = computed(() => !!(parentData?.lazy.value || props.lazy))\n\nconst computedActive = computed(() => isActive.value && !props.disabled)\nconst showSlot = computed(\n () =>\n computedActive.value ||\n !computedLazy.value ||\n (computedLazy.value && !props.unmountLazy && lazyRenderCompleted.value)\n)\n\nwatch(showSlot, (shown) => {\n if (shown && !lazyRenderCompleted.value) lazyRenderCompleted.value = true\n})\n\nwatch(isActive, (active) => {\n if (active) {\n activeModel.value = true\n setTimeout(() => {\n show.value = true\n }, 0)\n return\n }\n show.value = false\n activeModel.value = false\n})\n\nwatch(activeModel, (active) => {\n if (props.disabled) {\n activeModel.value = false\n return\n }\n if (!parentData) return\n if (!active) {\n if (isActive.value) {\n parentData.activateTab(undefined)\n }\n return\n }\n if (!isActive.value) {\n parentData.activateTab(internalId.value)\n }\n})\n\nconst computedClasses = computed(() => [\n {\n 'active': isActive.value,\n 'show': show.value,\n 'card-body': parentData?.card.value && props.noBody === false,\n 'fade': !parentData?.noFade.value,\n },\n show.value ? parentData?.activeTabClass.value : parentData?.inactiveTabClass.value,\n parentData?.tabClass.value,\n])\n\ndefineExpose({\n activate: () => {\n activeModel.value = true\n },\n deactivate: () => {\n activeModel.value = false\n },\n})\n</script>\n","<template>\n <component :is=\"props.tag\" :id=\"props.id\" class=\"tabs\" :class=\"computedClasses\">\n <ReusableEmptyTab.define>\n <div class=\"tab-content\" :class=\"props.contentClass\">\n <slot />\n <div\n v-if=\"showEmpty\"\n key=\"bv-empty-tab\"\n class=\"tab-pane active\"\n :class=\"{'card-body': props.card}\"\n >\n <slot name=\"empty\" />\n </div>\n </div>\n </ReusableEmptyTab.define>\n\n <ReusableEmptyTab.reuse v-if=\"props.end\" />\n <div\n :class=\"[\n props.navWrapperClass,\n {'card-header': props.card, 'ms-auto': vertical && props.end},\n ]\"\n >\n <ul\n class=\"nav\"\n :class=\"[navTabsClasses, props.navClass]\"\n role=\"tablist\"\n :aria-orientation=\"props.vertical ? 'vertical' : 'horizontal'\"\n >\n <slot name=\"tabs-start\" />\n <li\n v-for=\"(tab, idx) in tabs\"\n :key=\"tab.id ?? tab.internalId\"\n class=\"nav-item\"\n :class=\"tab.titleItemClass\"\n role=\"presentation\"\n >\n <button\n :id=\"tab.buttonId\"\n class=\"nav-link\"\n :class=\"[tab.navItemClasses, tab.titleLinkClass]\"\n role=\"tab\"\n :aria-controls=\"tab.id\"\n :aria-selected=\"tab.active\"\n :disabled=\"tab.disabled\"\n :tabindex=\"props.noKeyNav ? undefined : tab.active ? undefined : -1\"\n type=\"button\"\n v-bind=\"tab.titleLinkAttrs\"\n @keydown.left.exact=\"!props.vertical && keynav($event, -1)\"\n @keydown.left.shift=\"!props.vertical && keynav($event, -999)\"\n @keydown.up.exact=\"props.vertical && keynav($event, -1)\"\n @keydown.up.shift=\"props.vertical && keynav($event, -999)\"\n @keydown.right.exact=\"!props.vertical && keynav($event, 1)\"\n @keydown.right.shift=\"!props.vertical && keynav($event, 999)\"\n @keydown.down.exact=\"props.vertical && keynav($event, 1)\"\n @keydown.down.shift=\"props.vertical && keynav($event, 999)\"\n @keydown.page-up=\"keynav($event, -999)\"\n @keydown.page-down=\"keynav($event, 999)\"\n @keydown.home=\"keynav($event, -999)\"\n @keydown.end=\"keynav($event, 999)\"\n @click.stop=\"(e) => handleClick(e, idx)\"\n >\n <component :is=\"tab.titleComponent\" v-if=\"tab.titleComponent\" />\n <template v-else>\n {{ tab.title }}\n </template>\n </button>\n </li>\n <slot name=\"tabs-end\" />\n </ul>\n </div>\n <ReusableEmptyTab.reuse v-if=\"!props.end\" />\n </component>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n type Ref,\n ref,\n toRef,\n unref,\n type VNode,\n watch,\n} from 'vue'\nimport {BvEvent} from '../../utils/classes'\nimport {useAlignment} from '../../composables/useAlignment'\nimport {useId} from '../../composables/useId'\nimport {createReusableTemplate} from '@vueuse/core'\nimport type {TabType, BTabsProps, BTabsEmits, BTabsSlots} from '../../types'\nimport {tabsInjectionKey} from '../../utils/keys'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {getSafeDocument, sortSlotElementsByPosition} from '../../utils/dom'\nimport {flattenFragments} from '../../utils/flattenFragments'\nimport BTab from './BTab.vue'\n\nconst _props = withDefaults(defineProps<Omit<BTabsProps, 'modelValue' | 'activeIndex'>>(), {\n activeNavItemClass: undefined,\n activeTabClass: undefined,\n align: undefined,\n card: false,\n contentClass: undefined,\n end: false,\n fill: false,\n id: undefined,\n inactiveNavItemClass: undefined,\n inactiveTabClass: undefined,\n justified: false,\n lazy: false,\n navClass: undefined,\n navItemClass: undefined,\n navWrapperClass: undefined,\n noFade: false,\n noKeyNav: false,\n noNavStyle: false,\n pills: false,\n small: false,\n tag: 'div',\n tabClass: undefined,\n underline: false,\n vertical: false,\n})\nconst props = useDefaults(_props, 'BTabs')\nconst emit = defineEmits<BTabsEmits>()\nconst slots = defineSlots<BTabsSlots>()\n\nconst activeIndex = defineModel<Exclude<BTabsProps['index'], undefined>>('index', {\n default: -1,\n})\nconst activeId = defineModel<BTabsProps['modelValue']>({\n default: undefined,\n})\n\nconst ReusableEmptyTab = createReusableTemplate()\n\nconst tabsInternal = ref<Ref<TabType>[]>([])\n\nconst tabElementsArray = ref<VNode[]>([])\n\nconst isChildActive = ref(false)\nconst initialIds = ref<string[]>([])\nconst hasExplicitIds = ref(false)\n\nconst updateTabElementsArray = () => {\n const tabElements = flattenFragments(slots.default?.({}) ?? [])\n tabElementsArray.value = (Array.isArray(tabElements) ? tabElements : [tabElements]).filter(\n (tab) => tab.type === BTab\n )\n // only get the ids once in setup context\n if (initialIds.value.length === 0) {\n // we need to get the ids of the tabs before they are registered. After that we use the internalId for the tabpane\n initialIds.value = tabElementsArray.value.map((tab) =>\n unref(useId(() => tab.props?.id, 'tabpane'))\n )\n // Check if any tab has an explicit ID\n hasExplicitIds.value = tabElementsArray.value.some((tab) => tab.props?.id !== undefined)\n }\n isChildActive.value = tabElementsArray.value.some(\n (tab) => tab.props?.active !== undefined && tab.props?.active !== false\n )\n}\nupdateTabElementsArray()\n\nwatch(\n () => slots.default?.({}),\n () => {\n updateTabElementsArray()\n nextTick(() => {\n sortTabs()\n })\n }\n)\n\nconst tabs = computed(() => {\n if (tabsInternal.value.length === 0) {\n // fail back on the slot elements, the children haven't been registered yet\n const _activeIndex = tabElementsArray.value.findIndex(\n (tab) =>\n (tab.props?.active !== undefined &&\n (tab.props.disabled === false || tab.props.disabled === undefined)) ||\n (activeId.value && tab.props?.id === activeId.value)\n )\n return tabElementsArray.value.map((tab, index) => {\n const active =\n _activeIndex !== -1\n ? index === _activeIndex\n : activeIndex.value > -1\n ? index === activeIndex.value\n : index === 0\n return {\n id: tab.props?.id ?? initialIds.value[index],\n internalId: `premount-${index}`, // temporary id for the tab\n buttonId: tab.props?.buttonId,\n disabled: tab.props?.disabled,\n title: tab.props?.title,\n titleComponent: (tab.children as {title: unknown})?.title,\n titleItemClass: tab.props?.titleItemClass,\n titleLinkAttrs: tab.props?.titleLinkAttrs,\n titleLinkClass: tab.props?.titleLinkClass,\n onClick: tab.props?.onClick,\n active,\n navItemClasses: [\n {\n active,\n disabled: !(tab.props?.disabled === false || tab.props?.disabled === undefined),\n },\n active ? props.activeNavItemClass : props.inactiveNavItemClass,\n props.navItemClass,\n ],\n }\n })\n }\n return tabsInternal.value.map((_tab) => {\n const tab = unref(_tab)\n const active = tab.id === activeId.value\n\n return {\n ...tab,\n active,\n navItemClasses: [\n {\n active,\n disabled: tab.disabled,\n },\n active ? props.activeNavItemClass : props.inactiveNavItemClass,\n props.navItemClass,\n ],\n }\n })\n})\n\nlet initialized = false\nlet updateInitialActiveIndex = false\nlet updateInitialActiveId = false\nlet delayedTabSelection = false\n\n// Check if we need to delay tab selection:\n// - We have v-model:index (activeIndex) but no v-model (activeId)\n// - AND tabs don't have explicit IDs (will use generated IDs)\n// - AND we have tabs to select from\nconst needsDelayedSelection =\n activeIndex.value > -1 &&\n !activeId.value &&\n !hasExplicitIds.value &&\n tabElementsArray.value.length > 0\n\nif (needsDelayedSelection) {\n // Delay tab selection until children register with their generated IDs\n delayedTabSelection = true\n updateInitialActiveId = true\n} else if (activeIndex.value === -1 && activeId.value) {\n if (tabs.value.findIndex((t) => t.id === activeId.value) !== -1) {\n activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value)\n } else {\n updateInitialActiveIndex = true\n }\n} else if (activeIndex.value > -1 && !activeId.value) {\n if (tabs.value[activeIndex.value]?.id) {\n activeId.value = tabs.value[activeIndex.value]?.id\n } else {\n updateInitialActiveId = true\n }\n} else if (activeIndex.value === -1 && !activeId.value && !isChildActive.value) {\n activeIndex.value = tabs.value.findIndex((t) => t.disabled === undefined || t.disabled === false)\n activeId.value = tabs.value[activeIndex.value]?.id\n} else if (activeIndex.value === -1 && !activeId.value && isChildActive.value) {\n activeIndex.value = tabs.value.findIndex(\n (t) =>\n t.active !== undefined &&\n t.active !== false &&\n (t.disabled === undefined || t.disabled === false)\n )\n activeId.value = tabs.value[activeIndex.value]?.id\n}\n\nfunction updateInitialIndexAndId() {\n // we get the computedIds after registering the tabs\n if (updateInitialActiveIndex) {\n const index = tabs.value.findIndex((t) => t.id === activeId.value)\n if (index !== -1) {\n nextTick(() => {\n activeIndex.value = index\n updateInitialActiveIndex = false\n })\n }\n }\n if (updateInitialActiveId) {\n // Wait for tabs to be registered if we're doing delayed selection\n if (delayedTabSelection && tabsInternal.value.length === 0) {\n // Children haven't registered yet, wait\n return\n }\n if (activeIndex.value > -1 && tabs.value[activeIndex.value]?.id) {\n nextTick(() => {\n activeId.value = tabs.value[activeIndex.value]?.id\n updateInitialActiveId = false\n delayedTabSelection = false\n })\n }\n }\n}\n\nupdateInitialIndexAndId()\n\nconst showEmpty = computed(() => !(tabs?.value && tabs.value.length > 0))\n\nconst computedClasses = computed(() => ({\n 'd-flex': props.vertical,\n 'align-items-start': props.vertical,\n}))\n\nconst alignment = useAlignment(() => props.align)\n\nconst navTabsClasses = computed(() => ({\n 'nav-pills': props.pills,\n 'nav-underline': props.underline,\n 'flex-column me-3': props.vertical,\n [alignment.value]: props.align !== undefined,\n 'nav-fill': props.fill,\n 'card-header-tabs': props.card && !props.pills && !props.underline,\n 'card-header-pills': props.card && props.pills,\n 'nav-justified': props.justified,\n 'nav-tabs': !props.noNavStyle && !props.pills && !props.underline,\n 'small': props.small,\n}))\n\nconst handleClick = (event: Readonly<MouseEvent>, index: number) => {\n if (\n index >= 0 &&\n !tabs.value[index]?.disabled &&\n tabs.value[index]?.onClick &&\n typeof tabs.value[index].onClick === 'function'\n ) {\n tabs.value[index].onClick?.(event)\n if (event.defaultPrevented) {\n getSafeDocument()?.getElementById(tabs.value[index].buttonId)?.blur()\n return\n }\n }\n activeIndex.value = index\n}\n\nconst keynav = (e: Event, direction: number) => {\n if (tabs.value.length <= 0 || props.noKeyNav) return\n e.preventDefault()\n e.stopPropagation()\n activeIndex.value = nextIndex(activeIndex.value + direction, direction)\n nextTick(() => {\n if (activeIndex.value >= 0) {\n getSafeDocument()?.getElementById(tabs.value[activeIndex.value]?.buttonId)?.focus()\n }\n })\n}\n\nconst nextIndex = (start: number, direction: number) => {\n let index = start\n let minIdx = -1\n let maxIdx = -1\n\n for (let i = 0; i < tabs.value.length; i++) {\n if (!tabs.value[i]?.disabled) {\n if (minIdx === -1) minIdx = i\n maxIdx = i\n }\n }\n\n while (index >= minIdx && index <= maxIdx && tabs.value[index]?.disabled) {\n index += direction\n }\n\n if (index < minIdx) index = minIdx\n if (index > maxIdx) index = maxIdx\n\n return index\n}\n\nlet previousIndex: number | undefined\nlet isReverting = false\nwatch(activeIndex, (newValue, oldValue) => {\n // Early exit if there are no tabs or all tabs are disabled\n if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {\n return\n }\n\n // If we're reverting due to a prevented event, don't process further\n if (isReverting) {\n isReverting = false\n return\n }\n // Calculate the next valid index\n const index = nextIndex(newValue, newValue > oldValue ? 1 : -1)\n if (index !== newValue) {\n // If the index is not the same as the new value, set the previous index to the old value\n // this is to prevent the event from being emitted twice\n previousIndex = oldValue\n activeIndex.value = index\n return\n }\n // Emit the activate-tab event\n const tabEvent = new BvEvent('activate-tab', {cancelable: true})\n emit('activate-tab', {\n newTabId: tabs.value[index]?.id,\n prevTabId: tabs.value[previousIndex ?? oldValue]?.id,\n newTabIndex: index,\n prevTabIndex: previousIndex ?? oldValue,\n event: tabEvent,\n })\n // If the event is prevented, revert to the previous index\n if (tabEvent.defaultPrevented) {\n isReverting = true\n const prev = previousIndex ?? oldValue ?? nextIndex(0, 1)\n previousIndex = undefined\n // Update the active id this will also trigger the activeId watch which will update the activeIndex\n // this is to make sure we handle case that starts with id change.\n if (activeId.value !== tabs.value[prev]?.id) {\n activeId.value = tabs.value[prev]?.id\n }\n nextTick(() => {\n if (prev >= 0) {\n getSafeDocument()?.getElementById(tabs.value[prev]?.buttonId)?.focus()\n }\n })\n return\n }\n\n // Update the active id\n if (activeId.value !== tabs.value[index]?.id) {\n activeId.value = tabs.value[index]?.id\n }\n previousIndex = undefined\n})\n\nwatch(activeId, (newValue, oldValue) => {\n if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {\n return\n }\n const index = tabs.value.findIndex((t) => t.id === newValue)\n // If the new tab is the same as the current tab, do nothing\n if (index === activeIndex.value) return\n const oldIndex = tabs.value.findIndex((t) => t.id === oldValue)\n // If the new tab is disabled, find the next enabled tab\n if (tabs.value[index]?.disabled) {\n // activeIndex watcher will update the activeId to the next enabled tab\n activeIndex.value = nextIndex(index, index > oldIndex ? 1 : -1)\n return\n }\n // If the new tab is not found, find the first enabled tab\n if (index === -1) {\n // activeIndex watcher will update the activeId to the first enabled tab\n activeIndex.value = nextIndex(0, 1)\n nextTick(() => {\n activeId.value = tabs.value[activeIndex.value]?.id\n })\n return\n }\n // change to the next tab\n activeIndex.value = index\n})\n\nconst registerTab = (tab: Ref<TabType>) => {\n const idx = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId)\n if (idx === -1) {\n tabsInternal.value.push(tab)\n if (initialized) {\n nextTick(() => {\n sortTabs()\n })\n } else {\n // If we're doing delayed tab selection, try to update now that a tab has registered\n if (delayedTabSelection) {\n nextTick(() => {\n updateInitialIndexAndId()\n })\n }\n }\n } else {\n tabsInternal.value[idx] = tab\n if (initialized) {\n // sort just in case the tab was moved\n sortTabs()\n }\n }\n const idx2 = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId)\n return tab.value.id ?? (!initialized ? initialIds.value[idx2] : tab.value.internalId)\n}\n\nonMounted(() => {\n updateInitialIndexAndId()\n sortTabs()\n initialized = true\n})\n\nconst sortTabs = () => {\n tabsInternal.value.sort((a, b) => sortSlotElementsByPosition(a.value.el.value, b.value.el.value))\n if (\n activeId.value &&\n activeIndex.value !== tabs.value.findIndex((t) => t.id === activeId.value)\n ) {\n activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value)\n }\n}\n\nconst unregisterTab = (id: string) => {\n tabsInternal.value = tabsInternal.value.filter((t) => t.value.internalId !== id)\n}\n\nprovide(tabsInjectionKey, {\n lazy: toRef(() => props.lazy),\n card: toRef(() => props.card),\n noFade: toRef(() => props.noFade),\n activeTabClass: toRef(() => props.activeTabClass),\n inactiveTabClass: toRef(() => props.inactiveTabClass),\n tabClass: toRef(() => props.tabClass),\n registerTab,\n unregisterTab,\n activeId,\n activateTab: (internalId) => {\n const idx = tabs.value.findIndex((t) => t.internalId === internalId)\n if (internalId === undefined || idx === -1) {\n activeIndex.value = nextIndex(0, 1)\n return\n }\n activeIndex.value = idx\n },\n})\n</script>\n","<template>\n <component :is=\"props.tag\" :id=\"props.id\" class=\"tabs\" :class=\"computedClasses\">\n <ReusableEmptyTab.define>\n <div class=\"tab-content\" :class=\"props.contentClass\">\n <slot />\n <div\n v-if=\"showEmpty\"\n key=\"bv-empty-tab\"\n class=\"tab-pane active\"\n :class=\"{'card-body': props.card}\"\n >\n <slot name=\"empty\" />\n </div>\n </div>\n </ReusableEmptyTab.define>\n\n <ReusableEmptyTab.reuse v-if=\"props.end\" />\n <div\n :class=\"[\n props.navWrapperClass,\n {'card-header': props.card, 'ms-auto': vertical && props.end},\n ]\"\n >\n <ul\n class=\"nav\"\n :class=\"[navTabsClasses, props.navClass]\"\n role=\"tablist\"\n :aria-orientation=\"props.vertical ? 'vertical' : 'horizontal'\"\n >\n <slot name=\"tabs-start\" />\n <li\n v-for=\"(tab, idx) in tabs\"\n :key=\"tab.id ?? tab.internalId\"\n class=\"nav-item\"\n :class=\"tab.titleItemClass\"\n role=\"presentation\"\n >\n <button\n :id=\"tab.buttonId\"\n class=\"nav-link\"\n :class=\"[tab.navItemClasses, tab.titleLinkClass]\"\n role=\"tab\"\n :aria-controls=\"tab.id\"\n :aria-selected=\"tab.active\"\n :disabled=\"tab.disabled\"\n :tabindex=\"props.noKeyNav ? undefined : tab.active ? undefined : -1\"\n type=\"button\"\n v-bind=\"tab.titleLinkAttrs\"\n @keydown.left.exact=\"!props.vertical && keynav($event, -1)\"\n @keydown.left.shift=\"!props.vertical && keynav($event, -999)\"\n @keydown.up.exact=\"props.vertical && keynav($event, -1)\"\n @keydown.up.shift=\"props.vertical && keynav($event, -999)\"\n @keydown.right.exact=\"!props.vertical && keynav($event, 1)\"\n @keydown.right.shift=\"!props.vertical && keynav($event, 999)\"\n @keydown.down.exact=\"props.vertical && keynav($event, 1)\"\n @keydown.down.shift=\"props.vertical && keynav($event, 999)\"\n @keydown.page-up=\"keynav($event, -999)\"\n @keydown.page-down=\"keynav($event, 999)\"\n @keydown.home=\"keynav($event, -999)\"\n @keydown.end=\"keynav($event, 999)\"\n @click.stop=\"(e) => handleClick(e, idx)\"\n >\n <component :is=\"tab.titleComponent\" v-if=\"tab.titleComponent\" />\n <template v-else>\n {{ tab.title }}\n </template>\n </button>\n </li>\n <slot name=\"tabs-end\" />\n </ul>\n </div>\n <ReusableEmptyTab.reuse v-if=\"!props.end\" />\n </component>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n type Ref,\n ref,\n toRef,\n unref,\n type VNode,\n watch,\n} from 'vue'\nimport {BvEvent} from '../../utils/classes'\nimport {useAlignment} from '../../composables/useAlignment'\nimport {useId} from '../../composables/useId'\nimport {createReusableTemplate} from '@vueuse/core'\nimport type {TabType, BTabsProps, BTabsEmits, BTabsSlots} from '../../types'\nimport {tabsInjectionKey} from '../../utils/keys'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {getSafeDocument, sortSlotElementsByPosition} from '../../utils/dom'\nimport {flattenFragments} from '../../utils/flattenFragments'\nimport BTab from './BTab.vue'\n\nconst _props = withDefaults(defineProps<Omit<BTabsProps, 'modelValue' | 'activeIndex'>>(), {\n activeNavItemClass: undefined,\n activeTabClass: undefined,\n align: undefined,\n card: false,\n contentClass: undefined,\n end: false,\n fill: false,\n id: undefined,\n inactiveNavItemClass: undefined,\n inactiveTabClass: undefined,\n justified: false,\n lazy: false,\n navClass: undefined,\n navItemClass: undefined,\n navWrapperClass: undefined,\n noFade: false,\n noKeyNav: false,\n noNavStyle: false,\n pills: false,\n small: false,\n tag: 'div',\n tabClass: undefined,\n underline: false,\n vertical: false,\n})\nconst props = useDefaults(_props, 'BTabs')\nconst emit = defineEmits<BTabsEmits>()\nconst slots = defineSlots<BTabsSlots>()\n\nconst activeIndex = defineModel<Exclude<BTabsProps['index'], undefined>>('index', {\n default: -1,\n})\nconst activeId = defineModel<BTabsProps['modelValue']>({\n default: undefined,\n})\n\nconst ReusableEmptyTab = createReusableTemplate()\n\nconst tabsInternal = ref<Ref<TabType>[]>([])\n\nconst tabElementsArray = ref<VNode[]>([])\n\nconst isChildActive = ref(false)\nconst initialIds = ref<string[]>([])\nconst hasExplicitIds = ref(false)\n\nconst updateTabElementsArray = () => {\n const tabElements = flattenFragments(slots.default?.({}) ?? [])\n tabElementsArray.value = (Array.isArray(tabElements) ? tabElements : [tabElements]).filter(\n (tab) => tab.type === BTab\n )\n // only get the ids once in setup context\n if (initialIds.value.length === 0) {\n // we need to get the ids of the tabs before they are registered. After that we use the internalId for the tabpane\n initialIds.value = tabElementsArray.value.map((tab) =>\n unref(useId(() => tab.props?.id, 'tabpane'))\n )\n // Check if any tab has an explicit ID\n hasExplicitIds.value = tabElementsArray.value.some((tab) => tab.props?.id !== undefined)\n }\n isChildActive.value = tabElementsArray.value.some(\n (tab) => tab.props?.active !== undefined && tab.props?.active !== false\n )\n}\nupdateTabElementsArray()\n\nwatch(\n () => slots.default?.({}),\n () => {\n updateTabElementsArray()\n nextTick(() => {\n sortTabs()\n })\n }\n)\n\nconst tabs = computed(() => {\n if (tabsInternal.value.length === 0) {\n // fail back on the slot elements, the children haven't been registered yet\n const _activeIndex = tabElementsArray.value.findIndex(\n (tab) =>\n (tab.props?.active !== undefined &&\n (tab.props.disabled === false || tab.props.disabled === undefined)) ||\n (activeId.value && tab.props?.id === activeId.value)\n )\n return tabElementsArray.value.map((tab, index) => {\n const active =\n _activeIndex !== -1\n ? index === _activeIndex\n : activeIndex.value > -1\n ? index === activeIndex.value\n : index === 0\n return {\n id: tab.props?.id ?? initialIds.value[index],\n internalId: `premount-${index}`, // temporary id for the tab\n buttonId: tab.props?.buttonId,\n disabled: tab.props?.disabled,\n title: tab.props?.title,\n titleComponent: (tab.children as {title: unknown})?.title,\n titleItemClass: tab.props?.titleItemClass,\n titleLinkAttrs: tab.props?.titleLinkAttrs,\n titleLinkClass: tab.props?.titleLinkClass,\n onClick: tab.props?.onClick,\n active,\n navItemClasses: [\n {\n active,\n disabled: !(tab.props?.disabled === false || tab.props?.disabled === undefined),\n },\n active ? props.activeNavItemClass : props.inactiveNavItemClass,\n props.navItemClass,\n ],\n }\n })\n }\n return tabsInternal.value.map((_tab) => {\n const tab = unref(_tab)\n const active = tab.id === activeId.value\n\n return {\n ...tab,\n active,\n navItemClasses: [\n {\n active,\n disabled: tab.disabled,\n },\n active ? props.activeNavItemClass : props.inactiveNavItemClass,\n props.navItemClass,\n ],\n }\n })\n})\n\nlet initialized = false\nlet updateInitialActiveIndex = false\nlet updateInitialActiveId = false\nlet delayedTabSelection = false\n\n// Check if we need to delay tab selection:\n// - We have v-model:index (activeIndex) but no v-model (activeId)\n// - AND tabs don't have explicit IDs (will use generated IDs)\n// - AND we have tabs to select from\nconst needsDelayedSelection =\n activeIndex.value > -1 &&\n !activeId.value &&\n !hasExplicitIds.value &&\n tabElementsArray.value.length > 0\n\nif (needsDelayedSelection) {\n // Delay tab selection until children register with their generated IDs\n delayedTabSelection = true\n updateInitialActiveId = true\n} else if (activeIndex.value === -1 && activeId.value) {\n if (tabs.value.findIndex((t) => t.id === activeId.value) !== -1) {\n activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value)\n } else {\n updateInitialActiveIndex = true\n }\n} else if (activeIndex.value > -1 && !activeId.value) {\n if (tabs.value[activeIndex.value]?.id) {\n activeId.value = tabs.value[activeIndex.value]?.id\n } else {\n updateInitialActiveId = true\n }\n} else if (activeIndex.value === -1 && !activeId.value && !isChildActive.value) {\n activeIndex.value = tabs.value.findIndex((t) => t.disabled === undefined || t.disabled === false)\n activeId.value = tabs.value[activeIndex.value]?.id\n} else if (activeIndex.value === -1 && !activeId.value && isChildActive.value) {\n activeIndex.value = tabs.value.findIndex(\n (t) =>\n t.active !== undefined &&\n t.active !== false &&\n (t.disabled === undefined || t.disabled === false)\n )\n activeId.value = tabs.value[activeIndex.value]?.id\n}\n\nfunction updateInitialIndexAndId() {\n // we get the computedIds after registering the tabs\n if (updateInitialActiveIndex) {\n const index = tabs.value.findIndex((t) => t.id === activeId.value)\n if (index !== -1) {\n nextTick(() => {\n activeIndex.value = index\n updateInitialActiveIndex = false\n })\n }\n }\n if (updateInitialActiveId) {\n // Wait for tabs to be registered if we're doing delayed selection\n if (delayedTabSelection && tabsInternal.value.length === 0) {\n // Children haven't registered yet, wait\n return\n }\n if (activeIndex.value > -1 && tabs.value[activeIndex.value]?.id) {\n nextTick(() => {\n activeId.value = tabs.value[activeIndex.value]?.id\n updateInitialActiveId = false\n delayedTabSelection = false\n })\n }\n }\n}\n\nupdateInitialIndexAndId()\n\nconst showEmpty = computed(() => !(tabs?.value && tabs.value.length > 0))\n\nconst computedClasses = computed(() => ({\n 'd-flex': props.vertical,\n 'align-items-start': props.vertical,\n}))\n\nconst alignment = useAlignment(() => props.align)\n\nconst navTabsClasses = computed(() => ({\n 'nav-pills': props.pills,\n 'nav-underline': props.underline,\n 'flex-column me-3': props.vertical,\n [alignment.value]: props.align !== undefined,\n 'nav-fill': props.fill,\n 'card-header-tabs': props.card && !props.pills && !props.underline,\n 'card-header-pills': props.card && props.pills,\n 'nav-justified': props.justified,\n 'nav-tabs': !props.noNavStyle && !props.pills && !props.underline,\n 'small': props.small,\n}))\n\nconst handleClick = (event: Readonly<MouseEvent>, index: number) => {\n if (\n index >= 0 &&\n !tabs.value[index]?.disabled &&\n tabs.value[index]?.onClick &&\n typeof tabs.value[index].onClick === 'function'\n ) {\n tabs.value[index].onClick?.(event)\n if (event.defaultPrevented) {\n getSafeDocument()?.getElementById(tabs.value[index].buttonId)?.blur()\n return\n }\n }\n activeIndex.value = index\n}\n\nconst keynav = (e: Event, direction: number) => {\n if (tabs.value.length <= 0 || props.noKeyNav) return\n e.preventDefault()\n e.stopPropagation()\n activeIndex.value = nextIndex(activeIndex.value + direction, direction)\n nextTick(() => {\n if (activeIndex.value >= 0) {\n getSafeDocument()?.getElementById(tabs.value[activeIndex.value]?.buttonId)?.focus()\n }\n })\n}\n\nconst nextIndex = (start: number, direction: number) => {\n let index = start\n let minIdx = -1\n let maxIdx = -1\n\n for (let i = 0; i < tabs.value.length; i++) {\n if (!tabs.value[i]?.disabled) {\n if (minIdx === -1) minIdx = i\n maxIdx = i\n }\n }\n\n while (index >= minIdx && index <= maxIdx && tabs.value[index]?.disabled) {\n index += direction\n }\n\n if (index < minIdx) index = minIdx\n if (index > maxIdx) index = maxIdx\n\n return index\n}\n\nlet previousIndex: number | undefined\nlet isReverting = false\nwatch(activeIndex, (newValue, oldValue) => {\n // Early exit if there are no tabs or all tabs are disabled\n if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {\n return\n }\n\n // If we're reverting due to a prevented event, don't process further\n if (isReverting) {\n isReverting = false\n return\n }\n // Calculate the next valid index\n const index = nextIndex(newValue, newValue > oldValue ? 1 : -1)\n if (index !== newValue) {\n // If the index is not the same as the new value, set the previous index to the old value\n // this is to prevent the event from being emitted twice\n previousIndex = oldValue\n activeIndex.value = index\n return\n }\n // Emit the activate-tab event\n const tabEvent = new BvEvent('activate-tab', {cancelable: true})\n emit('activate-tab', {\n newTabId: tabs.value[index]?.id,\n prevTabId: tabs.value[previousIndex ?? oldValue]?.id,\n newTabIndex: index,\n prevTabIndex: previousIndex ?? oldValue,\n event: tabEvent,\n })\n // If the event is prevented, revert to the previous index\n if (tabEvent.defaultPrevented) {\n isReverting = true\n const prev = previousIndex ?? oldValue ?? nextIndex(0, 1)\n previousIndex = undefined\n // Update the active id this will also trigger the activeId watch which will update the activeIndex\n // this is to make sure we handle case that starts with id change.\n if (activeId.value !== tabs.value[prev]?.id) {\n activeId.value = tabs.value[prev]?.id\n }\n nextTick(() => {\n if (prev >= 0) {\n getSafeDocument()?.getElementById(tabs.value[prev]?.buttonId)?.focus()\n }\n })\n return\n }\n\n // Update the active id\n if (activeId.value !== tabs.value[index]?.id) {\n activeId.value = tabs.value[index]?.id\n }\n previousIndex = undefined\n})\n\nwatch(activeId, (newValue, oldValue) => {\n if (tabs.value.length <= 0 || tabs.value.filter((t) => !t.disabled).length <= 0) {\n return\n }\n const index = tabs.value.findIndex((t) => t.id === newValue)\n // If the new tab is the same as the current tab, do nothing\n if (index === activeIndex.value) return\n const oldIndex = tabs.value.findIndex((t) => t.id === oldValue)\n // If the new tab is disabled, find the next enabled tab\n if (tabs.value[index]?.disabled) {\n // activeIndex watcher will update the activeId to the next enabled tab\n activeIndex.value = nextIndex(index, index > oldIndex ? 1 : -1)\n return\n }\n // If the new tab is not found, find the first enabled tab\n if (index === -1) {\n // activeIndex watcher will update the activeId to the first enabled tab\n activeIndex.value = nextIndex(0, 1)\n nextTick(() => {\n activeId.value = tabs.value[activeIndex.value]?.id\n })\n return\n }\n // change to the next tab\n activeIndex.value = index\n})\n\nconst registerTab = (tab: Ref<TabType>) => {\n const idx = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId)\n if (idx === -1) {\n tabsInternal.value.push(tab)\n if (initialized) {\n nextTick(() => {\n sortTabs()\n })\n } else {\n // If we're doing delayed tab selection, try to update now that a tab has registered\n if (delayedTabSelection) {\n nextTick(() => {\n updateInitialIndexAndId()\n })\n }\n }\n } else {\n tabsInternal.value[idx] = tab\n if (initialized) {\n // sort just in case the tab was moved\n sortTabs()\n }\n }\n const idx2 = tabsInternal.value.findIndex((t) => t.value.internalId === tab.value.internalId)\n return tab.value.id ?? (!initialized ? initialIds.value[idx2] : tab.value.internalId)\n}\n\nonMounted(() => {\n updateInitialIndexAndId()\n sortTabs()\n initialized = true\n})\n\nconst sortTabs = () => {\n tabsInternal.value.sort((a, b) => sortSlotElementsByPosition(a.value.el.value, b.value.el.value))\n if (\n activeId.value &&\n activeIndex.value !== tabs.value.findIndex((t) => t.id === activeId.value)\n ) {\n activeIndex.value = tabs.value.findIndex((t) => t.id === activeId.value)\n }\n}\n\nconst unregisterTab = (id: string) => {\n tabsInternal.value = tabsInternal.value.filter((t) => t.value.internalId !== id)\n}\n\nprovide(tabsInjectionKey, {\n lazy: toRef(() => props.lazy),\n card: toRef(() => props.card),\n noFade: toRef(() => props.noFade),\n activeTabClass: toRef(() => props.activeTabClass),\n inactiveTabClass: toRef(() => props.inactiveTabClass),\n tabClass: toRef(() => props.tabClass),\n registerTab,\n unregisterTab,\n activeId,\n activateTab: (internalId) => {\n const idx = tabs.value.findIndex((t) => t.internalId === internalId)\n if (internalId === undefined || idx === -1) {\n activeIndex.value = nextIndex(0, 1)\n return\n }\n activeIndex.value = idx\n },\n})\n</script>\n"],"mappings":"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