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 • 13 kB
Source Map (JSON)
{"version":3,"file":"BOffcanvas-BsLF8xkS.mjs","sources":["../src/components/BOffcanvas/BOffcanvas.vue"],"sourcesContent":["<template>\n <ConditionalTeleport\n :to=\"props.teleportTo\"\n :disabled=\"props.teleportDisabled || isOpenByBreakpoint\"\n >\n <Transition\n v-if=\"renderRef || contentShowing || isOpenByBreakpoint\"\n v-bind=\"transitionProps\"\n :appear=\"modelValue || props.visible\"\n >\n <div\n v-show=\"\n (showRef && ((backdropReady && props.backdropFirst) || !props.backdropFirst)) ||\n isOpenByBreakpoint\n \"\n :id=\"computedId\"\n ref=\"_element\"\n aria-modal=\"true\"\n role=\"dialog\"\n :class=\"computedClasses\"\n :style=\"computedStyles\"\n tabindex=\"-1\"\n :aria-labelledby=\"`${computedId}-offcanvas-label`\"\n data-bs-backdrop=\"false\"\n v-bind=\"$attrs\"\n >\n <template v-if=\"contentShowing || isOpenByBreakpoint\">\n <div v-if=\"!props.noHeader\" class=\"offcanvas-header\" :class=\"props.headerClass\">\n <slot name=\"header\" v-bind=\"sharedSlots\">\n <h5 :id=\"`${computedId}-offcanvas-label`\" class=\"offcanvas-title\">\n <slot name=\"title\" v-bind=\"sharedSlots\">\n {{ props.title }}\n </slot>\n </h5>\n <template v-if=\"!props.noHeaderClose\">\n <BButton v-if=\"hasHeaderCloseSlot\" v-bind=\"headerCloseAttrs\" @click=\"hide('close')\">\n <slot name=\"header-close\" />\n </BButton>\n <BCloseButton\n v-else\n :aria-label=\"props.headerCloseLabel\"\n v-bind=\"headerCloseAttrs\"\n @click=\"hide('close')\"\n />\n </template>\n </slot>\n </div>\n <div class=\"offcanvas-body\" :class=\"props.bodyClass\" v-bind=\"props.bodyAttrs\">\n <slot v-bind=\"sharedSlots\" />\n </div>\n <div v-if=\"hasFooterSlot\" :class=\"props.footerClass\">\n <slot name=\"footer\" v-bind=\"sharedSlots\" />\n </div>\n </template>\n <div\n v-if=\"needsFallback\"\n ref=\"_fallbackFocusElement\"\n :class=\"fallbackClassSelector\"\n tabindex=\"0\"\n style=\"width: 0; height: 0; overflow: hidden\"\n />\n </div>\n </Transition>\n <slot v-if=\"!props.noBackdrop\" name=\"backdrop\" v-bind=\"sharedSlots\">\n <Transition v-if=\"renderBackdropRef\" v-bind=\"backdropTransitionProps\">\n <div\n v-show=\"showBackdrop\"\n class=\"offcanvas-backdrop\"\n :class=\"{\n fade: !computedNoAnimation,\n show: backdropVisible || computedNoAnimation,\n }\"\n @click=\"hide('backdrop')\"\n />\n </Transition>\n </slot>\n </ConditionalTeleport>\n</template>\n\n<script setup lang=\"ts\">\nimport {breakpointsBootstrapV5, onKeyStroke, useBreakpoints, useFocus} from '@vueuse/core'\nimport {useActivatedFocusTrap} from '../../composables/useActivatedFocusTrap'\nimport {computed, type EmitFn, nextTick, ref, useTemplateRef, watch} from 'vue'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {useId} from '../../composables/useId'\nimport type {BOffcanvasProps} from '../../types/ComponentProps'\nimport {BvTriggerableEvent} from '../../utils'\nimport BButton from '../BButton/BButton.vue'\nimport BCloseButton from '../BButton/BCloseButton.vue'\nimport ConditionalTeleport from '../ConditionalTeleport.vue'\nimport {useSafeScrollLock} from '../../composables/useSafeScrollLock'\nimport {isEmptySlot} from '../../utils/dom'\nimport {type showHideEmits, useShowHide} from '../../composables/useShowHide'\nimport type {Placement} from '../../types/Alignment'\n\n// TODO once the responsive stuff may be implemented correctly,\n// What needs to occur is a fixing of the \"body scrolling\".\n// If the offcanvas is on the screen on a large screen, body scrolling is not disabled\n// Even though the modelValue is true\n// When it's a small screen and close, it works, as normal,\n// But then when it opens up on a small screen, it must disable again\n// This is implemented on Layout.vue, but is not officially supported.\n\ndefineOptions({\n inheritAttrs: false,\n})\n\nconst _props = withDefaults(defineProps<Omit<BOffcanvasProps, 'modelValue'>>(), {\n backdropFirst: false,\n bodyAttrs: undefined,\n bodyClass: undefined,\n bodyScrolling: false,\n footerClass: undefined,\n headerClass: undefined,\n headerCloseClass: undefined,\n headerCloseLabel: 'Close',\n headerCloseVariant: 'secondary',\n id: undefined,\n initialAnimation: false,\n lazy: false,\n noAnimation: false,\n noBackdrop: false,\n noCloseOnBackdrop: false,\n noCloseOnEsc: false,\n noTrap: false,\n noFocus: false,\n noHeader: false,\n noHeaderClose: false,\n unmountLazy: false,\n placement: 'start',\n shadow: false,\n teleportDisabled: false,\n teleportTo: 'body',\n title: undefined,\n show: false,\n width: undefined,\n visible: false,\n})\nconst props = useDefaults(_props, 'BOffcanvas')\n\nconst emit = defineEmits<\n {\n close: [value: BvTriggerableEvent]\n esc: [value: BvTriggerableEvent]\n backdrop: [value: BvTriggerableEvent]\n breakpoint: [value: BvTriggerableEvent]\n } & showHideEmits\n>()\n\ntype SharedSlotsData = {\n visible: boolean\n placement: Placement\n hide: (trigger?: string) => void\n}\n\nconst slots = defineSlots<{\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'backdrop'?: (props: SharedSlotsData) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'default'?: (props: SharedSlotsData) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'footer'?: (props: SharedSlotsData) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'header'?: (props: SharedSlotsData) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'header-close'?: (props: Record<string, never>) => any\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n 'title'?: (props: SharedSlotsData) => any\n}>()\n\nconst modelValue = defineModel<Exclude<BOffcanvasProps['modelValue'], undefined>>({\n default: false,\n})\n\nconst computedId = useId(() => props.id, 'offcanvas')\n\nconst breakpoints = useBreakpoints(breakpointsBootstrapV5)\nconst smallerOrEqualToBreakpoint = breakpoints.smallerOrEqual(() => props.responsive ?? 'xs')\n\nconst isOpenByBreakpoint = ref(props.responsive !== undefined && !smallerOrEqualToBreakpoint.value)\n\nconst element = useTemplateRef<HTMLElement>('_element')\nconst fallbackFocusElement = useTemplateRef<HTMLElement>('_fallbackFocusElement')\n\nconst onAfterEnter = () => {\n nextTick(() => {\n if (props.noFocus === false && !isOpenByBreakpoint.value) {\n focused.value = true\n }\n })\n}\n\nconst {\n showRef,\n renderRef,\n renderBackdropRef,\n hide,\n show,\n toggle,\n computedNoAnimation,\n contentShowing,\n transitionProps,\n backdropReady,\n backdropTransitionProps,\n backdropVisible,\n isVisible,\n buildTriggerableEvent,\n localNoAnimation,\n isLeaving,\n trapActive,\n} = useShowHide(modelValue, props, emit as EmitFn, element, computedId, {\n transitionProps: {\n onAfterEnter,\n enterToClass: 'showing',\n leaveToClass: 'hiding',\n enterActiveClass: '',\n leaveActiveClass: '',\n enterFromClass: '',\n leaveFromClass: '',\n },\n})\n\nuseSafeScrollLock(showRef, () => props.bodyScrolling || isOpenByBreakpoint.value)\n\nonKeyStroke(\n 'Escape',\n () => {\n hide('esc')\n },\n {target: element}\n)\n\nconst {focused} = useFocus(element, {\n initialValue: modelValue.value && props.noFocus === false && !isOpenByBreakpoint.value,\n})\n\nconst fallbackClassSelector = 'offcanvas-fallback-focus'\n\nconst {needsFallback} = useActivatedFocusTrap({\n element,\n isActive: trapActive,\n noTrap: () => props.noTrap || isOpenByBreakpoint.value,\n fallbackFocus: {\n classSelector: fallbackClassSelector,\n ref: fallbackFocusElement,\n },\n})\n\nconst showBackdrop = computed(\n () =>\n (props.responsive === undefined || !isOpenByBreakpoint.value) &&\n props.noBackdrop === false &&\n (showRef.value === true ||\n (isLeaving.value && props.backdropFirst && !computedNoAnimation.value))\n)\n\nconst hasHeaderCloseSlot = computed(() => !isEmptySlot(slots['header-close']))\nconst headerCloseClasses = computed(() => [\n {'text-reset': !hasHeaderCloseSlot.value},\n props.headerCloseClass,\n])\nconst headerCloseAttrs = computed(() => ({\n variant: hasHeaderCloseSlot.value ? props.headerCloseVariant : undefined,\n class: headerCloseClasses.value,\n}))\n\nconst hasFooterSlot = computed(() => !isEmptySlot(slots.footer))\nconst computedClasses = computed(() => [\n props.responsive === undefined ? 'offcanvas' : `offcanvas-${props.responsive}`,\n `offcanvas-${props.placement}`,\n {\n 'show': isVisible.value,\n [`shadow-${props.shadow}`]: !!props.shadow,\n 'no-transition': computedNoAnimation.value,\n },\n])\n\nconst computedStyles = computed(() => ({\n width: props.width,\n}))\n\nconst sharedSlots = computed<SharedSlotsData>(() => ({\n visible: showRef.value,\n placement: props.placement,\n hide,\n}))\n\nwatch(smallerOrEqualToBreakpoint, (newValue) => {\n if (props.responsive === undefined) return\n if (newValue === true) {\n localNoAnimation.value = true\n requestAnimationFrame(() => {\n isOpenByBreakpoint.value = false\n })\n emit('breakpoint', buildTriggerableEvent('breakpoint'))\n emit('hide', buildTriggerableEvent('hide'))\n } else {\n localNoAnimation.value = true\n requestAnimationFrame(() => {\n isOpenByBreakpoint.value = true\n })\n emit('breakpoint', buildTriggerableEvent('breakpoint'))\n emit('show', buildTriggerableEvent('show'))\n }\n})\n\ndefineExpose({\n hide,\n show,\n toggle,\n})\n</script>\n\n<style lang=\"scss\" scoped>\n.no-transition {\n transition: none !important;\n}\n</style>\n"],"names":["_useSlots","_useModel"],"mappings":"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"}