bootstrap-vue-next
Version:
Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development
518 lines (517 loc) • 21.4 kB
JavaScript
require("./chunk-CoQrYLCe.js");
const require_keys = require("./keys-durSVUrO.js");
const require_dist = require("./dist-B_c893QG.js");
const require_dom = require("./dom-Bs6DzM72.js");
const require_useDefaults = require("./useDefaults-DsLf4iRY.js");
const require_useId = require("./useId-DHrBgM7P.js");
const require_useShowHide = require("./useShowHide-sLzwukNm.js");
const require_useColorVariantClasses = require("./useColorVariantClasses-CEfOwjPv.js");
const require_BButton = require("./BButton-sb1cBCIb.js");
const require_BCloseButton = require("./BCloseButton-CN__Jjcj.js");
const require_ConditionalTeleport = require("./ConditionalTeleport-BJZk6HAx.js");
const require_getElement = require("./getElement-BPm7tpe2.js");
const require_useSafeScrollLock = require("./useSafeScrollLock-xJBEvCQ7.js");
let vue = require("vue");
//#region src/composables/useModalManager.ts
var modalOpenClassName = "modal-open";
var useSharedModalStack = () => {
const modalManagerPlugin = (0, vue.inject)(require_keys.modalManagerKey, null);
/**
* Removes an item from both the stack and registry
*/
const dispose = (modal) => {
modalManagerPlugin?.removeStack(modal);
modalManagerPlugin?.removeRegistry(modal);
};
const updateHTMLAttrs = require_dist.getSSRHandler("updateHTMLAttrs", (selector, attribute, value) => {
const el = typeof selector !== "string" ? require_dist.unrefElement(selector) : selector ? require_dom.getSafeDocument()?.querySelector(selector) : void 0;
if (!el) return;
if (attribute === "class") el.classList.toggle(modalOpenClassName, value === modalOpenClassName);
else el.setAttribute(attribute, value);
});
require_dist.tryOnScopeDispose(() => {
if (modalManagerPlugin?.countStack.value === 0) updateHTMLAttrs("body", "class", "");
});
(0, vue.watch)(() => modalManagerPlugin?.countStack.value, (newValue) => {
if (newValue === void 0) return;
updateHTMLAttrs("body", "class", newValue > 0 ? modalOpenClassName : "");
});
return {
...modalManagerPlugin,
dispose
};
};
var useModalManager = (modalOpen, initialValue) => {
const { pushRegistry, pushStack, removeStack, stack, dispose, countStack } = useSharedModalStack();
const currentModal = (0, vue.getCurrentInstance)();
if (!currentModal || currentModal.type.__name !== "BModal") throw new Error("useModalManager must only use in BModal component");
pushRegistry?.(currentModal);
require_dist.tryOnScopeDispose(() => {
dispose(currentModal);
});
const setInStack = (newValue, oldValue) => {
if (newValue) pushStack?.(currentModal);
else if (oldValue && !newValue) removeStack?.(currentModal);
};
setInStack(initialValue, initialValue);
(0, vue.watch)(modalOpen, setInStack);
return {
activePosition: (0, vue.computed)(() => stack?.value.findIndex((el) => (0, vue.toValue)(el.exposed?.id) === (0, vue.toValue)(currentModal.exposed?.id))),
activeModalCount: countStack,
stackWithoutSelf: (0, vue.computed)(() => stack?.value.filter((el) => (0, vue.toValue)(el.exposed?.id) !== (0, vue.toValue)(currentModal.exposed?.id)) ?? [])
};
};
//#endregion
//#region src/components/BModal/BModal.vue?vue&type=script&setup=true&lang.ts
var _hoisted_1 = [
"id",
"aria-labelledby",
"aria-describedby"
];
var _hoisted_2 = ["id"];
var fallbackClassSelector = "modal-fallback-focus";
//#endregion
//#region src/components/BModal/BModal.vue
var BModal_default = /* @__PURE__ */ (0, vue.defineComponent)({
inheritAttrs: false,
__name: "BModal",
props: /* @__PURE__ */ (0, vue.mergeModels)({
focus: {
type: [
String,
Boolean,
Object,
null
],
default: void 0
},
backdropFirst: {
type: Boolean,
default: false
},
body: { default: void 0 },
bodyAttrs: { default: void 0 },
bodyBgVariant: { default: null },
bodyClass: { default: null },
bodyScrolling: {
type: Boolean,
default: false
},
bodyTextVariant: { default: null },
bodyVariant: { default: null },
busy: {
type: Boolean,
default: false
},
buttonSize: { default: "md" },
cancelClass: { default: void 0 },
cancelDisabled: {
type: Boolean,
default: false
},
cancelTitle: { default: "Cancel" },
cancelVariant: { default: "secondary" },
centered: {
type: Boolean,
default: false
},
contentClass: { default: void 0 },
dialogClass: { default: void 0 },
footerBgVariant: { default: null },
footerBorderVariant: { default: null },
footerClass: { default: void 0 },
footerTextVariant: { default: null },
footerVariant: { default: null },
fullscreen: {
type: [Boolean, String],
default: false
},
headerAttrs: { default: void 0 },
headerBgVariant: { default: null },
headerBorderVariant: { default: null },
headerClass: { default: void 0 },
headerCloseClass: { default: void 0 },
headerCloseLabel: { default: "Close" },
headerCloseVariant: { default: "secondary" },
headerTextVariant: { default: null },
headerVariant: { default: null },
noBackdrop: {
type: Boolean,
default: false
},
noFooter: {
type: Boolean,
default: false
},
noHeader: {
type: Boolean,
default: false
},
noHeaderClose: {
type: Boolean,
default: false
},
id: { default: void 0 },
modalClass: { default: void 0 },
noCloseOnBackdrop: {
type: Boolean,
default: false
},
noCloseOnEsc: {
type: Boolean,
default: false
},
noTrap: {
type: Boolean,
default: false
},
noStacking: { type: Boolean },
okClass: { default: void 0 },
okDisabled: {
type: Boolean,
default: false
},
okOnly: {
type: Boolean,
default: false
},
okTitle: { default: "OK" },
okVariant: { default: "primary" },
scrollable: {
type: Boolean,
default: false
},
size: { default: "md" },
title: { default: void 0 },
titleClass: { default: void 0 },
titleVisuallyHidden: {
type: Boolean,
default: false
},
titleTag: { default: "h5" },
teleportDisabled: {
type: Boolean,
default: false
},
teleportTo: { default: "body" },
initialAnimation: {
type: Boolean,
default: false
},
noAnimation: { type: Boolean },
noFade: {
type: Boolean,
default: false
},
lazy: {
type: Boolean,
default: false
},
unmountLazy: {
type: Boolean,
default: false
},
show: {
type: Boolean,
default: false
},
transProps: { default: void 0 },
visible: {
type: Boolean,
default: false
}
}, {
"modelValue": {
type: Boolean,
default: false
},
"modelModifiers": {}
}),
emits: /* @__PURE__ */ (0, vue.mergeModels)([
"backdrop",
"cancel",
"close",
"esc",
"ok",
"hide",
"hide-prevented",
"hidden",
"show",
"show-prevented",
"shown",
"toggle",
"toggle-prevented"
], ["update:modelValue"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = require_useDefaults.useDefaults(__props, "BModal");
const emit = __emit;
const slots = (0, vue.useSlots)();
const computedId = require_useId.useId(() => props.id, "modal");
const modelValue = (0, vue.useModel)(__props, "modelValue");
const element = (0, vue.useTemplateRef)("_element");
const fallbackFocusElement = (0, vue.useTemplateRef)("_fallbackFocusElement");
const okButton = (0, vue.useTemplateRef)("_okButton");
const cancelButton = (0, vue.useTemplateRef)("_cancelButton");
const closeButton = (0, vue.useTemplateRef)("_closeButton");
const pickFocusItem = () => {
if (props.focus && typeof props.focus !== "boolean") {
if (props.focus === "ok") return okButton;
else if (props.focus === "close") return closeButton;
else if (props.focus === "cancel") return cancelButton;
return require_getElement.getElement(props.focus, element.value ?? void 0) ?? element.value;
}
return element;
};
let activeElement = null;
const onAfterEnter = () => {
const doc = require_dom.getSafeDocument();
if (props.noTrap && props.focus !== false && doc) {
activeElement = doc.activeElement;
if (activeElement === element.value) activeElement = null;
const el = require_dist.unrefElement(pickFocusItem());
if (!el) return;
el?.focus();
if (el.tagName && el.tagName.toLowerCase() === "input" && typeof el.select === "function") el.select();
}
};
const onAfterLeave = () => {
if (props.noTrap && props.focus !== false && activeElement) {
activeElement?.focus();
activeElement = null;
}
};
const { showRef, renderRef, renderBackdropRef, hide, show, toggle, computedNoAnimation, transitionProps, backdropTransitionProps, isLeaving, isVisible, trapActive, contentShowing, backdropReady, backdropVisible } = require_useShowHide.useShowHide(modelValue, props, emit, element, computedId, { transitionProps: {
onAfterEnter,
onAfterLeave
} });
const { needsFallback } = require_useSafeScrollLock.useActivatedFocusTrap({
element,
isActive: trapActive,
noTrap: () => props.noTrap,
fallbackFocus: {
ref: fallbackFocusElement,
classSelector: fallbackClassSelector
},
focus: () => props.focus === false ? false : require_dist.unrefElement(pickFocusItem()) ?? void 0
});
require_dist.onKeyStroke("Escape", () => {
hide("esc");
}, { target: element });
require_useSafeScrollLock.useSafeScrollLock(showRef, () => props.bodyScrolling);
const hasHeaderCloseSlot = (0, vue.computed)(() => !require_dom.isEmptySlot(slots["header-close"]));
const modalDialogClasses = (0, vue.computed)(() => [props.dialogClass, {
"modal-fullscreen": props.fullscreen === true,
[`modal-fullscreen-${props.fullscreen}-down`]: typeof props.fullscreen === "string",
[`modal-${props.size}`]: props.size !== "md",
"modal-dialog-centered": props.centered,
"modal-dialog-scrollable": props.scrollable
}]);
const bodyColorClasses = require_useColorVariantClasses.useColorVariantClasses(() => ({
bgVariant: props.bodyBgVariant,
textVariant: props.bodyTextVariant,
variant: props.bodyVariant
}));
const bodyClasses = (0, vue.computed)(() => [props.bodyClass, bodyColorClasses.value]);
const headerColorClasses = require_useColorVariantClasses.useColorVariantClasses(() => ({
bgVariant: props.headerBgVariant,
textVariant: props.headerTextVariant,
variant: props.headerVariant,
borderVariant: props.headerBorderVariant
}));
const headerClasses = (0, vue.computed)(() => [props.headerClass, headerColorClasses.value]);
const headerCloseAttrs = (0, vue.computed)(() => ({
variant: hasHeaderCloseSlot.value ? props.headerCloseVariant : void 0,
class: props.headerCloseClass
}));
const footerColorClasses = require_useColorVariantClasses.useColorVariantClasses(() => ({
bgVariant: props.footerBgVariant,
textVariant: props.footerTextVariant,
variant: props.footerVariant,
borderVariant: props.footerBorderVariant
}));
const footerClasses = (0, vue.computed)(() => [props.footerClass, footerColorClasses.value]);
const titleClasses = (0, vue.computed)(() => [props.titleClass, { ["visually-hidden"]: props.titleVisuallyHidden }]);
const disableCancel = (0, vue.computed)(() => props.cancelDisabled || props.busy);
const disableOk = (0, vue.computed)(() => props.okDisabled || props.busy);
const { activePosition, activeModalCount, stackWithoutSelf } = useModalManager(showRef, modelValue.value);
const sharedClasses = (0, vue.computed)(() => ({
[`stack-position-${activePosition?.value ?? 0}`]: true,
[`stack-inverse-position-${(activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0)}`]: true
}));
(0, vue.watch)(stackWithoutSelf, (newValue, oldValue) => {
if (newValue.length > oldValue.length && showRef.value === true && props.noStacking) hide();
});
const defaultModalDialogZIndex = (0, vue.ref)(require_dom.getModalZIndex(element.value ?? require_dom.getSafeDocument()?.body));
(0, vue.onMounted)(() => {
(0, vue.watch)(renderRef, (v) => {
if (!v) return;
(0, vue.nextTick)(() => {
if (!element.value) return;
defaultModalDialogZIndex.value = require_dom.getModalZIndex(element.value);
});
}, { immediate: true });
});
const computedZIndexNumber = (0, vue.computed)(() => showRef.value || isLeaving.value ? defaultModalDialogZIndex.value - ((activeModalCount?.value ?? 0) * 2 - (activePosition?.value ?? 0) * 2) : defaultModalDialogZIndex.value);
const computedZIndex = (0, vue.computed)(() => ({
"z-index": computedZIndexNumber.value,
"--b-position": activePosition?.value ?? 0,
"--b-inverse-position": (activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0),
"--b-count": activeModalCount?.value ?? 0
}));
const computedZIndexBackdrop = (0, vue.computed)(() => ({
"z-index": computedZIndexNumber.value - 1,
"--b-position": activePosition?.value ?? 0,
"--b-inverse-position": (activeModalCount?.value ?? 1) - 1 - (activePosition?.value ?? 0),
"--b-count": activeModalCount?.value ?? 0
}));
const sharedSlots = (0, vue.computed)(() => ({
id: computedId.value,
cancel: () => {
hide("cancel");
},
close: () => {
hide("close");
},
hide,
show,
toggle,
ok: () => {
hide("ok");
},
active: showRef.value,
visible: showRef.value
}));
__expose({
hide,
id: computedId,
show,
toggle,
visible: showRef
});
return (_ctx, _cache) => {
return (0, vue.openBlock)(), (0, vue.createBlock)(require_ConditionalTeleport.ConditionalTeleport_default, {
to: (0, vue.unref)(props).teleportTo,
disabled: (0, vue.unref)(props).teleportDisabled
}, {
default: (0, vue.withCtx)(() => [(0, vue.unref)(renderRef) || (0, vue.unref)(contentShowing) ? ((0, vue.openBlock)(), (0, vue.createBlock)(vue.Transition, (0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(transitionProps), { appear: modelValue.value || (0, vue.unref)(props).visible }), {
default: (0, vue.withCtx)(() => [(0, vue.withDirectives)((0, vue.createElementVNode)("div", (0, vue.mergeProps)({
id: (0, vue.unref)(computedId),
ref: "_element",
class: ["modal", [(0, vue.unref)(props).modalClass, {
fade: !(0, vue.unref)(computedNoAnimation),
show: (0, vue.unref)(isVisible),
...sharedClasses.value
}]],
role: "dialog",
"aria-labelledby": !(0, vue.unref)(props).noHeader ? `${(0, vue.unref)(computedId)}-label` : void 0,
"aria-describedby": `${(0, vue.unref)(computedId)}-body`,
tabindex: "-1"
}, _ctx.$attrs, {
style: [computedZIndex.value, { "display": "block" }],
onMousedown: _cache[4] || (_cache[4] = (0, vue.withModifiers)(($event) => (0, vue.unref)(hide)("backdrop"), ["left", "self"]))
}), [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["modal-dialog", modalDialogClasses.value]) }, [(0, vue.unref)(contentShowing) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 0,
class: (0, vue.normalizeClass)(["modal-content", (0, vue.unref)(props).contentClass])
}, [
!(0, vue.unref)(props).noHeader ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", (0, vue.mergeProps)({
key: 0,
class: ["modal-header", headerClasses.value]
}, (0, vue.unref)(props).headerAttrs), [(0, vue.renderSlot)(_ctx.$slots, "header", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(props).titleTag), {
id: `${(0, vue.unref)(computedId)}-label`,
class: (0, vue.normalizeClass)(["modal-title", titleClasses.value])
}, {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "title", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(props).title), 1)])]),
_: 3
}, 8, ["id", "class"])), !(0, vue.unref)(props).noHeaderClose ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [hasHeaderCloseSlot.value ? ((0, vue.openBlock)(), (0, vue.createBlock)(require_BButton.BButton_default, (0, vue.mergeProps)({
key: 0,
ref: "_closeButton"
}, headerCloseAttrs.value, { onClick: _cache[0] || (_cache[0] = ($event) => (0, vue.unref)(hide)("close")) }), {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "header-close", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)))]),
_: 3
}, 16)) : ((0, vue.openBlock)(), (0, vue.createBlock)(require_BCloseButton.BCloseButton_default, (0, vue.mergeProps)({
key: 1,
ref: "_closeButton",
"aria-label": (0, vue.unref)(props).headerCloseLabel
}, headerCloseAttrs.value, { onClick: _cache[1] || (_cache[1] = ($event) => (0, vue.unref)(hide)("close")) }), null, 16, ["aria-label"]))], 64)) : (0, vue.createCommentVNode)("", true)])], 16)) : (0, vue.createCommentVNode)("", true),
(0, vue.createElementVNode)("div", (0, vue.mergeProps)({
id: `${(0, vue.unref)(computedId)}-body`,
class: ["modal-body", bodyClasses.value]
}, (0, vue.unref)(props).bodyAttrs), [(0, vue.renderSlot)(_ctx.$slots, "default", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(props).body), 1)])], 16, _hoisted_2),
!(0, vue.unref)(props).noFooter ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 1,
class: (0, vue.normalizeClass)(["modal-footer", footerClasses.value])
}, [(0, vue.renderSlot)(_ctx.$slots, "footer", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [(0, vue.renderSlot)(_ctx.$slots, "cancel", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [!(0, vue.unref)(props).okOnly ? ((0, vue.openBlock)(), (0, vue.createBlock)(require_BButton.BButton_default, {
key: 0,
ref: "_cancelButton",
disabled: disableCancel.value,
size: (0, vue.unref)(props).buttonSize,
variant: (0, vue.unref)(props).cancelVariant,
class: (0, vue.normalizeClass)((0, vue.unref)(props).cancelClass),
onClick: _cache[2] || (_cache[2] = ($event) => (0, vue.unref)(hide)("cancel"))
}, {
default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(props).cancelTitle), 1)]),
_: 1
}, 8, [
"disabled",
"size",
"variant",
"class"
])) : (0, vue.createCommentVNode)("", true)]), (0, vue.renderSlot)(_ctx.$slots, "ok", (0, vue.normalizeProps)((0, vue.guardReactiveProps)(sharedSlots.value)), () => [(0, vue.createVNode)(require_BButton.BButton_default, {
ref: "_okButton",
disabled: disableOk.value,
size: (0, vue.unref)(props).buttonSize,
variant: (0, vue.unref)(props).okVariant,
class: (0, vue.normalizeClass)((0, vue.unref)(props).okClass),
onClick: _cache[3] || (_cache[3] = ($event) => (0, vue.unref)(hide)("ok"))
}, {
default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(props).okTitle), 1)]),
_: 1
}, 8, [
"disabled",
"size",
"variant",
"class"
])])])], 2)) : (0, vue.createCommentVNode)("", true)
], 2)) : (0, vue.createCommentVNode)("", true)], 2), (0, vue.unref)(needsFallback) ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
key: 0,
ref: "_fallbackFocusElement",
class: (0, vue.normalizeClass)(fallbackClassSelector),
tabindex: "0",
style: {
"width": "0",
"height": "0",
"overflow": "hidden"
}
}, null, 512)) : (0, vue.createCommentVNode)("", true)], 16, _hoisted_1), [[vue.vShow, (0, vue.unref)(showRef) && ((0, vue.unref)(backdropReady) && (0, vue.unref)(props).backdropFirst || !(0, vue.unref)(props).backdropFirst)]])]),
_: 3
}, 16, ["appear"])) : (0, vue.createCommentVNode)("", true), !(0, vue.unref)(props).noBackdrop ? (0, vue.renderSlot)(_ctx.$slots, "backdrop", (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 1 }, sharedSlots.value)), () => [(0, vue.unref)(renderBackdropRef) ? ((0, vue.openBlock)(), (0, vue.createBlock)(vue.Transition, (0, vue.normalizeProps)((0, vue.mergeProps)({ key: 0 }, (0, vue.unref)(backdropTransitionProps))), {
default: (0, vue.withCtx)(() => [(0, vue.withDirectives)((0, vue.createElementVNode)("div", {
class: (0, vue.normalizeClass)(["modal-backdrop", {
fade: !(0, vue.unref)(computedNoAnimation),
show: (0, vue.unref)(backdropVisible) || (0, vue.unref)(computedNoAnimation),
...sharedClasses.value
}]),
style: (0, vue.normalizeStyle)(computedZIndexBackdrop.value),
onClick: _cache[5] || (_cache[5] = ($event) => (0, vue.unref)(hide)("backdrop"))
}, null, 6), [[vue.vShow, (0, vue.unref)(showRef) || (0, vue.unref)(isLeaving) && (0, vue.unref)(props).backdropFirst && !(0, vue.unref)(computedNoAnimation)]])]),
_: 1
}, 16)) : (0, vue.createCommentVNode)("", true)]) : (0, vue.createCommentVNode)("", true)]),
_: 3
}, 8, ["to", "disabled"]);
};
}
});
//#endregion
Object.defineProperty(exports, "BModal_default", {
enumerable: true,
get: function() {
return BModal_default;
}
});
Object.defineProperty(exports, "useSharedModalStack", {
enumerable: true,
get: function() {
return useSharedModalStack;
}
});
//# sourceMappingURL=BModal-CVf686JS.js.map