UNPKG

bootstrap-vue-next

Version:

BootstrapVueNext is an early and lovely component library for Vue 3 & Nuxt 3 based on Bootstrap 5 and Typescript.

1 lines 16 kB
{"version":3,"file":"BDropdown-Csgw4gsr.mjs","sources":["../src/components/BDropdown/BDropdown.vue"],"sourcesContent":["<template>\n <ConditionalWrapper\n :skip=\"inInputGroup || props.noWrapper\"\n :class=\"computedClasses\"\n :role=\"inButtonGroupAttributes?.role\"\n >\n <BButton\n :id=\"computedId\"\n ref=\"_splitButton\"\n :variant=\"props.splitVariant || props.variant\"\n :size=\"props.size\"\n :class=\"buttonClasses\"\n :disabled=\"props.splitDisabled || props.disabled\"\n :type=\"props.splitButtonType\"\n :aria-label=\"props.ariaLabel\"\n :aria-expanded=\"props.split ? undefined : showRef\"\n :aria-haspopup=\"props.split ? undefined : 'menu'\"\n :href=\"props.split ? props.splitHref : undefined\"\n :to=\"props.split && props.splitTo ? props.splitTo : undefined\"\n @click=\"onSplitClick\"\n >\n <slot name=\"button-content\"> {{ props.text }} </slot>\n </BButton>\n <BButton\n v-if=\"props.split\"\n :id=\"computedId + '-split'\"\n ref=\"_button\"\n :variant=\"props.variant\"\n :size=\"props.size\"\n :disabled=\"props.disabled\"\n :class=\"[props.toggleClass, {show: showRef}]\"\n class=\"dropdown-toggle-split dropdown-toggle\"\n :aria-expanded=\"showRef\"\n aria-haspopup=\"menu\"\n @click=\"onButtonClick\"\n >\n <span class=\"visually-hidden\">\n <slot name=\"toggle-text\">\n {{ props.toggleText }}\n </slot>\n </span>\n </BButton>\n <ConditionalTeleport\n :to=\"props.teleportTo\"\n :disabled=\"!props.teleportTo || props.teleportDisabled\"\n >\n <Transition\n v-if=\"renderRef || contentShowing\"\n v-bind=\"transitionProps\"\n :appear=\"modelValue || props.visible\"\n >\n <ul\n v-show=\"showRef\"\n :id=\"computedId + '-menu'\"\n ref=\"_floating\"\n :style=\"[floatingStyles, sizeStyles]\"\n class=\"dropdown-menu overflow-auto\"\n :class=\"[props.menuClass, computedMenuClasses]\"\n :aria-labelledby=\"computedId\"\n :role=\"props.role\"\n @click=\"onClickInside\"\n >\n <slot v-if=\"contentShowing\" :hide=\"hide\" :show=\"show\" :visible=\"showRef\" />\n </ul>\n </Transition>\n </ConditionalTeleport>\n </ConditionalWrapper>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n autoUpdate,\n type Boundary,\n flip,\n type Middleware,\n offset as offsetMiddleware,\n type RootBoundary,\n shift,\n size as sizeMiddleware,\n useFloating,\n} from '@floating-ui/vue'\nimport {onClickOutside, onKeyStroke, useToNumber} from '@vueuse/core'\nimport {\n computed,\n type CSSProperties,\n type EmitFn,\n inject,\n nextTick,\n provide,\n ref,\n toRef,\n useTemplateRef,\n watch,\n} from 'vue'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {useId} from '../../composables/useId'\nimport type {BDropdownProps} from '../../types/ComponentProps'\nimport BButton from '../BButton/BButton.vue'\nimport ConditionalWrapper from '../ConditionalWrapper.vue'\nimport ConditionalTeleport from '../ConditionalTeleport.vue'\nimport {isBoundary, isRootBoundary} from '../../utils/floatingUi'\nimport {getElement} from '../../utils/getElement'\nimport {buttonGroupKey, dropdownInjectionKey, inputGroupKey} from '../../utils/keys'\nimport {type showHideEmits, useShowHide} from '../../composables/useShowHide'\n\nconst _props = withDefaults(defineProps<Omit<BDropdownProps, 'modelValue'>>(), {\n ariaLabel: undefined,\n autoClose: true,\n boundary: 'clippingAncestors',\n boundaryPadding: undefined,\n teleportTo: undefined,\n teleportDisabled: false,\n disabled: false,\n floatingMiddleware: undefined,\n id: undefined,\n initialAnimation: false,\n isNav: false,\n lazy: false,\n menuClass: undefined,\n noCaret: false,\n noFade: false,\n noFlip: false,\n noShift: false,\n noSize: false,\n offset: 0,\n unmountLazy: false,\n role: 'menu',\n size: 'md',\n noWrapper: false,\n split: false,\n splitButtonType: 'button',\n splitClass: undefined,\n splitDisabled: undefined,\n splitHref: undefined,\n splitTo: undefined,\n placement: 'bottom-start',\n splitVariant: undefined,\n strategy: 'absolute',\n text: undefined,\n show: false,\n toggleClass: undefined,\n toggleText: 'Toggle dropdown',\n transProps: undefined,\n variant: 'secondary',\n visible: false,\n wrapperClass: undefined,\n})\nconst props = useDefaults(_props, 'BDropdown')\n\nconst emit = defineEmits<\n {\n click: [event: MouseEvent]\n } & showHideEmits\n>()\n\ndefineSlots<{\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'button-content'?: (props: Record<string, never>) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'default'?: (props: {hide: () => void; show: () => void; visible: boolean}) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'toggle-text'?: (props: Record<string, never>) => any\n}>()\n\nconst computedId = useId(() => props.id, 'dropdown')\n\nconst modelValue = defineModel<Exclude<BDropdownProps['modelValue'], undefined>>({default: false})\n\nconst inInputGroup = inject(inputGroupKey, false)\nconst inButtonGroup = inject(buttonGroupKey, false)\n\nconst computedOffset = computed(() =>\n typeof props.offset === 'string' || typeof props.offset === 'number' ? props.offset : NaN\n)\nconst offsetToNumber = useToNumber(computedOffset)\n\nconst floating = useTemplateRef<HTMLElement>('_floating')\nconst button = useTemplateRef<HTMLElement>('_button')\nconst splitButton = useTemplateRef<HTMLElement>('_splitButton')\n\nconst boundary = computed<Boundary | undefined>(() =>\n isBoundary(props.boundary) ? props.boundary : undefined\n)\nconst rootBoundary = computed<RootBoundary | undefined>(() =>\n isRootBoundary(props.boundary) ? props.boundary : undefined\n)\n\nconst referencePlacement = computed(() => (!props.split ? splitButton.value : button.value))\n\nconst {\n showRef,\n renderRef,\n hide,\n show,\n toggle,\n computedNoAnimation,\n transitionProps,\n contentShowing,\n isVisible,\n} = useShowHide(modelValue, props, emit as EmitFn, referencePlacement, computedId)\n\nconst computedMenuClasses = computed(() => [\n {\n show: isVisible.value,\n fade: !computedNoAnimation.value,\n },\n])\n\nonKeyStroke(\n 'Escape',\n () => {\n hide()\n getElement(referencePlacement.value)?.focus()\n },\n {target: referencePlacement}\n)\nonKeyStroke(\n 'Escape',\n () => {\n hide()\n getElement(referencePlacement.value)?.focus()\n },\n {target: floating}\n)\n\nconst keynav = (e: Readonly<Event>, v: number) => {\n if (floating.value?.contains((e.target as HTMLElement)?.closest('form'))) return\n if (/input|select|option|textarea|form/i.test((e.target as HTMLElement)?.tagName)) return\n e.preventDefault()\n if (!showRef.value) {\n show()\n const loop = setInterval(() => {\n if (isVisible.value) {\n clearInterval(loop)\n nextTick(() => keynav(e, v))\n }\n }, 16)\n return\n }\n const list = floating.value?.querySelectorAll('.dropdown-item:not(.disabled):not(:disabled)')\n if (!list) return\n if (floating.value?.contains(document.activeElement)) {\n const active = floating.value.querySelector('.dropdown-item:focus')\n const index = Array.prototype.indexOf.call(list, active) + v\n if (index >= 0 && index < list?.length) (list[index] as HTMLElement)?.focus()\n } else {\n ;(list[v === -1 ? list.length - 1 : 0] as HTMLElement)?.focus()\n }\n}\n\nonKeyStroke('ArrowUp', (e) => keynav(e, -1), {target: referencePlacement})\nonKeyStroke('ArrowDown', (e) => keynav(e, 1), {target: referencePlacement})\nonKeyStroke('ArrowUp', (e) => keynav(e, -1), {target: floating})\nonKeyStroke('ArrowDown', (e) => keynav(e, 1), {target: floating})\n\nconst sizeStyles = ref<CSSProperties>({})\nconst floatingMiddleware = computed<Middleware[]>(() => {\n if (props.floatingMiddleware !== undefined) {\n return props.floatingMiddleware\n }\n const localOffset =\n typeof props.offset === 'string' || typeof props.offset === 'number'\n ? offsetToNumber.value\n : props.offset\n const arr: Middleware[] = [offsetMiddleware(localOffset)]\n if (props.noFlip === false) {\n arr.push(\n flip({\n boundary: boundary.value,\n rootBoundary: rootBoundary.value,\n padding: props.boundaryPadding,\n })\n )\n }\n if (props.noShift === false) {\n arr.push(\n shift({\n boundary: boundary.value,\n rootBoundary: rootBoundary.value,\n padding: props.boundaryPadding,\n })\n )\n }\n if (props.noSize === false) {\n arr.push(\n sizeMiddleware({\n boundary: boundary.value,\n rootBoundary: rootBoundary.value,\n padding: props.boundaryPadding,\n apply({availableWidth, availableHeight}) {\n sizeStyles.value = {\n maxHeight:\n availableHeight >= (floating.value?.scrollHeight ?? 0)\n ? undefined\n : availableHeight\n ? `${Math.max(0, availableHeight)}px`\n : undefined,\n maxWidth:\n availableWidth >= (floating.value?.scrollWidth ?? 0)\n ? undefined\n : availableWidth\n ? `${Math.max(0, availableWidth)}px`\n : undefined,\n }\n },\n })\n )\n }\n return arr\n})\nconst {update, floatingStyles} = useFloating(referencePlacement, floating, {\n placement: () => props.placement,\n middleware: floatingMiddleware,\n strategy: toRef(() => props.strategy),\n whileElementsMounted: autoUpdate,\n})\n\nconst inButtonGroupAttributes = inButtonGroup\n ? {\n class: 'btn-group',\n role: 'group',\n }\n : undefined\n\nconst computedClasses = computed(() => [\n inButtonGroupAttributes?.class,\n props.wrapperClass,\n {\n 'btn-group': !props.wrapperClass && props.split,\n 'dropdown': !props.wrapperClass && !props.split,\n 'position-static': props.boundary !== 'clippingAncestors' && !props.isNav,\n },\n])\n\nconst buttonClasses = computed(() => [\n props.split ? props.splitClass : props.toggleClass,\n {\n 'nav-link': props.isNav,\n 'dropdown-toggle': !props.split,\n 'dropdown-toggle-no-caret': props.noCaret && !props.split,\n 'show': props.split ? undefined : showRef.value,\n },\n])\n\nconst onButtonClick = () => {\n toggle()\n}\n\nconst onSplitClick = (event: Readonly<MouseEvent>) => {\n if (props.split) {\n emit('click', event)\n return\n }\n onButtonClick()\n}\n\nonClickOutside(\n floating,\n () => {\n if (showRef.value && (props.autoClose === true || props.autoClose === 'outside')) {\n hide()\n }\n },\n {ignore: [button, splitButton]}\n)\nconst onClickInside = () => {\n if (showRef.value && (props.autoClose === true || props.autoClose === 'inside')) {\n hide()\n }\n}\n\nwatch(isVisible, () => {\n update()\n})\n\ndefineExpose({\n hide,\n show,\n toggle,\n})\n\nprovide(dropdownInjectionKey, {\n id: computedId,\n show,\n hide,\n toggle,\n visible: toRef(() => showRef.value),\n isNav: toRef(() => props.isNav),\n})\n</script>\n<style lang=\"scss\" scoped>\n.dropdown-menu {\n &.fade {\n display: block;\n }\n}\n</style>\n"],"names":["_useModel","offsetMiddleware","sizeMiddleware"],"mappings":"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"}