bootstrap-vue-next
Version:
BootstrapVueNext is an early and lovely component library for Vue 3 & Nuxt 3 based on Bootstrap 5 and Typescript.
313 lines (312 loc) • 14.1 kB
JavaScript
import { defineComponent, mergeModels, useSlots, useModel, useTemplateRef, ref, onMounted, computed, watch, createBlock, openBlock, unref, withCtx, createCommentVNode, renderSlot, Transition, mergeProps, withDirectives, createElementVNode, createElementBlock, Fragment, normalizeClass, normalizeProps, guardReactiveProps, createTextVNode, toDisplayString, vShow, nextTick } from "vue";
import { l as useBreakpoints, o as onKeyStroke, f as unrefElement, m as breakpointsBootstrapV5 } from "./index-CMqRvrZx.mjs";
import { a as useSafeScrollLock, u as useActivatedFocusTrap } from "./useSafeScrollLock-DX55jDcC.mjs";
import { u as useDefaults } from "./useDefaults-CzkRF2AY.mjs";
import { u as useId } from "./useId-BmZnPXsS.mjs";
import { _ as _sfc_main$2 } from "./BButton.vue_vue_type_script_setup_true_lang-CywtlN38.mjs";
import { _ as _sfc_main$3 } from "./BCloseButton.vue_vue_type_script_setup_true_lang-DjJD_nYp.mjs";
import { _ as _sfc_main$1 } from "./ConditionalTeleport.vue_vue_type_script_lang-BCI6afpC.mjs";
import { i as isEmptySlot } from "./dom-BK2w00Ec.mjs";
import { u as useShowHide } from "./useShowHide-CguGFDSN.mjs";
import { g as getElement } from "./getElement-WfnRgCbF.mjs";
import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.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 },
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 == null ? void 0 : focusElement.focus();
}
});
};
const {
showRef,
renderRef,
renderBackdropRef,
hide,
show,
toggle,
computedNoAnimation,
contentShowing,
transitionProps,
backdropReady,
backdropTransitionProps,
backdropVisible,
isVisible,
buildTriggerableEvent,
localNoAnimation,
isLeaving,
trapActive
} = 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(props.responsive !== void 0 && !smallerOrEqualToBreakpoint.value);
onMounted(() => {
if (props.responsive !== void 0)
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;
localNoAnimation.value = true;
requestAnimationFrame(() => {
isOpenByBreakpoint.value = opened;
});
emit("breakpoint", buildTriggerableEvent("breakpoint"), opened);
emit("hide", buildTriggerableEvent("hide"));
} else {
const opened = true;
localNoAnimation.value = 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", {
key: 0,
class: normalizeClass(["offcanvas-header", unref(props).headerClass])
}, [
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)
], true)
], 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)), void 0, true)
]),
_: 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)
], true)
], 2)) : createCommentVNode("", true),
createElementVNode("div", mergeProps({
class: ["offcanvas-body", unref(props).bodyClass]
}, unref(props).bodyAttrs), [
renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(sharedSlots.value)), void 0, true)
], 16),
hasFooterSlot.value ? (openBlock(), createElementBlock("div", {
key: 1,
class: normalizeClass(unref(props).footerClass)
}, [
renderSlot(_ctx.$slots, "footer", normalizeProps(guardReactiveProps(sharedSlots.value)), void 0, true)
], 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)
], true) : createCommentVNode("", true)
]),
_: 3
}, 8, ["to", "disabled"]);
};
}
});
const BOffcanvas = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d3f94528"]]);
export {
BOffcanvas as B
};
//# sourceMappingURL=BOffcanvas-DH1MW9Or.mjs.map