bootstrap-vue-next
Version:
BootstrapVueNext is an early and lovely component library for Vue 3 & Nuxt 3 based on Bootstrap 5 and Typescript.
357 lines (356 loc) • 14.8 kB
JavaScript
import { defineComponent, mergeModels, useModel, inject, computed, useTemplateRef, ref, toRef, watch, provide, openBlock, createBlock, unref, normalizeClass, withCtx, createVNode, renderSlot, createTextVNode, toDisplayString, createElementVNode, createCommentVNode, Transition, mergeProps, withDirectives, normalizeStyle, vShow, nextTick } from "vue";
import { i as isBoundary, d as isRootBoundary, f as flip, s as shift, e as size, g as useFloating, h as autoUpdate, o as offset } from "./floatingUi-DWL_DNW7.mjs";
import { o as onKeyStroke, k as onClickOutside } from "./index-Cr5Qd2ql.mjs";
import { u as useDefaults } from "./useDefaults-BTLXvYhO.mjs";
import { u as useId } from "./useId-c2wnQbyL.mjs";
import { _ as _sfc_main$2 } from "./BButton.vue_vue_type_script_setup_true_lang-Bifj7SBY.mjs";
import { _ as _sfc_main$1 } from "./ConditionalWrapper.vue_vue_type_script_lang-CUX3HBqw.mjs";
import { _ as _sfc_main$3 } from "./ConditionalTeleport.vue_vue_type_script_lang-2PJ2jBTg.mjs";
import { g as getElement } from "./getElement-D_JPfLJS.mjs";
import { l as inputGroupKey, h as buttonGroupKey, u as dropdownInjectionKey } from "./keys-41Cw9q6f.mjs";
import { u as useShowHide } from "./useShowHide-BJTVhfuo.mjs";
import { u as useToNumber } from "./index-D3jGjWWk.mjs";
import { _ as _export_sfc } from "./_plugin-vue_export-helper-1tPrXgE0.mjs";
const _hoisted_1 = { class: "visually-hidden" };
const _hoisted_2 = ["id", "aria-labelledby", "role"];
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "BDropdown",
props: /* @__PURE__ */ mergeModels({
ariaLabel: { default: void 0 },
autoClose: { type: [Boolean, String], default: true },
boundary: { default: "clippingAncestors" },
boundaryPadding: { default: void 0 },
disabled: { type: Boolean, default: false },
floatingMiddleware: { default: void 0 },
id: { default: void 0 },
isNav: { type: Boolean, default: false },
menuClass: { default: void 0 },
noCaret: { type: Boolean, default: false },
noFlip: { type: Boolean, default: false },
noShift: { type: Boolean, default: false },
noSize: { type: Boolean, default: false },
offset: { default: 0 },
role: { default: "menu" },
size: { default: "md" },
noWrapper: { type: Boolean, default: false },
split: { type: Boolean, default: false },
splitButtonType: { default: "button" },
splitClass: { default: void 0 },
splitDisabled: { type: Boolean, default: void 0 },
splitHref: { default: void 0 },
splitTo: { default: void 0 },
splitVariant: { default: void 0 },
strategy: { default: "absolute" },
text: { default: void 0 },
toggleClass: { default: void 0 },
toggleText: { default: "Toggle dropdown" },
variant: { default: "secondary" },
wrapperClass: { default: void 0 },
placement: { default: "bottom-start" },
teleportDisabled: { type: Boolean, default: false },
teleportTo: { default: void 0 },
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__ */ mergeModels(["click", "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, "BDropdown");
const emit = __emit;
const computedId = useId(() => props.id, "dropdown");
const modelValue = useModel(__props, "modelValue");
const inInputGroup = inject(inputGroupKey, false);
const inButtonGroup = inject(buttonGroupKey, false);
const computedOffset = computed(
() => typeof props.offset === "string" || typeof props.offset === "number" ? props.offset : NaN
);
const offsetToNumber = useToNumber(computedOffset);
const floating = useTemplateRef("_floating");
const button = useTemplateRef("_button");
const splitButton = useTemplateRef("_splitButton");
const boundary = computed(
() => isBoundary(props.boundary) ? props.boundary : void 0
);
const rootBoundary = computed(
() => isRootBoundary(props.boundary) ? props.boundary : void 0
);
const referencePlacement = computed(() => !props.split ? splitButton.value : button.value);
const {
showRef,
renderRef,
hide,
show,
toggle,
computedNoAnimation,
transitionProps,
contentShowing,
isVisible
} = useShowHide(modelValue, props, emit, referencePlacement, computedId);
const computedMenuClasses = computed(() => [
{
show: isVisible.value,
fade: !computedNoAnimation.value
}
]);
onKeyStroke(
"Escape",
() => {
var _a;
hide();
(_a = getElement(referencePlacement.value)) == null ? void 0 : _a.focus();
},
{ target: referencePlacement }
);
onKeyStroke(
"Escape",
() => {
var _a;
hide();
(_a = getElement(referencePlacement.value)) == null ? void 0 : _a.focus();
},
{ target: floating }
);
const keynav = (e, v) => {
var _a, _b, _c, _d, _e, _f, _g;
if ((_b = floating.value) == null ? void 0 : _b.contains((_a = e.target) == null ? void 0 : _a.closest("form"))) return;
if (/input|select|option|textarea|form/i.test((_c = e.target) == null ? void 0 : _c.tagName)) return;
e.preventDefault();
if (!showRef.value) {
show();
const loop = setInterval(() => {
if (isVisible.value) {
clearInterval(loop);
nextTick(() => keynav(e, v));
}
}, 16);
return;
}
const list = (_d = floating.value) == null ? void 0 : _d.querySelectorAll(".dropdown-item:not(.disabled):not(:disabled)");
if (!list) return;
if ((_e = floating.value) == null ? void 0 : _e.contains(document.activeElement)) {
const active = floating.value.querySelector(".dropdown-item:focus");
const index = Array.prototype.indexOf.call(list, active) + v;
if (index >= 0 && index < (list == null ? void 0 : list.length)) (_f = list[index]) == null ? void 0 : _f.focus();
} else {
(_g = list[v === -1 ? list.length - 1 : 0]) == null ? void 0 : _g.focus();
}
};
onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: referencePlacement });
onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: referencePlacement });
onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: floating });
onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: floating });
const sizeStyles = ref({});
const floatingMiddleware = computed(() => {
if (props.floatingMiddleware !== void 0) {
return props.floatingMiddleware;
}
const localOffset = typeof props.offset === "string" || typeof props.offset === "number" ? offsetToNumber.value : props.offset;
const arr = [offset(localOffset)];
if (props.noFlip === false) {
arr.push(
flip({
boundary: boundary.value,
rootBoundary: rootBoundary.value,
padding: props.boundaryPadding
})
);
}
if (props.noShift === false) {
arr.push(
shift({
boundary: boundary.value,
rootBoundary: rootBoundary.value,
padding: props.boundaryPadding
})
);
}
if (props.noSize === false) {
arr.push(
size({
boundary: boundary.value,
rootBoundary: rootBoundary.value,
padding: props.boundaryPadding,
apply({ availableWidth, availableHeight }) {
var _a, _b;
sizeStyles.value = {
maxHeight: availableHeight >= (((_a = floating.value) == null ? void 0 : _a.scrollHeight) ?? 0) ? void 0 : availableHeight ? `${Math.max(0, availableHeight)}px` : void 0,
maxWidth: availableWidth >= (((_b = floating.value) == null ? void 0 : _b.scrollWidth) ?? 0) ? void 0 : availableWidth ? `${Math.max(0, availableWidth)}px` : void 0
};
}
})
);
}
return arr;
});
const { update, floatingStyles } = useFloating(referencePlacement, floating, {
placement: () => props.placement,
middleware: floatingMiddleware,
strategy: toRef(() => props.strategy),
whileElementsMounted: autoUpdate
});
const inButtonGroupAttributes = inButtonGroup ? {
class: "btn-group",
role: "group"
} : void 0;
const computedClasses = computed(() => [
inButtonGroupAttributes == null ? void 0 : inButtonGroupAttributes.class,
props.wrapperClass,
{
"btn-group": !props.wrapperClass && props.split,
"dropdown": !props.wrapperClass && !props.split,
"position-static": props.boundary !== "clippingAncestors" && !props.isNav
}
]);
const buttonClasses = computed(() => [
props.split ? props.splitClass : props.toggleClass,
{
"nav-link": props.isNav,
"dropdown-toggle": !props.split,
"dropdown-toggle-no-caret": props.noCaret && !props.split,
"show": props.split ? void 0 : showRef.value
}
]);
const onButtonClick = () => {
toggle();
};
const onSplitClick = (event) => {
if (props.split) {
emit("click", event);
return;
}
onButtonClick();
};
onClickOutside(
floating,
() => {
if (showRef.value && (props.autoClose === true || props.autoClose === "outside")) {
hide();
}
},
{ ignore: [button, splitButton] }
);
const onClickInside = () => {
if (showRef.value && (props.autoClose === true || props.autoClose === "inside")) {
hide();
}
};
watch(isVisible, () => {
update();
});
__expose({
hide,
show,
toggle
});
provide(dropdownInjectionKey, {
id: computedId,
show,
hide,
toggle,
visible: toRef(() => showRef.value),
isNav: toRef(() => props.isNav)
});
return (_ctx, _cache) => {
var _a;
return openBlock(), createBlock(_sfc_main$1, {
skip: unref(inInputGroup) || unref(props).noWrapper,
class: normalizeClass(computedClasses.value),
role: (_a = unref(inButtonGroupAttributes)) == null ? void 0 : _a.role
}, {
default: withCtx(() => [
createVNode(_sfc_main$2, {
id: unref(computedId),
ref: "_splitButton",
variant: unref(props).splitVariant || unref(props).variant,
size: unref(props).size,
class: normalizeClass(buttonClasses.value),
disabled: unref(props).splitDisabled || unref(props).disabled,
type: unref(props).splitButtonType,
"aria-label": unref(props).ariaLabel,
"aria-expanded": unref(props).split ? void 0 : unref(showRef),
"aria-haspopup": unref(props).split ? void 0 : "menu",
href: unref(props).split ? unref(props).splitHref : void 0,
to: unref(props).split && unref(props).splitTo ? unref(props).splitTo : void 0,
onClick: onSplitClick
}, {
default: withCtx(() => [
renderSlot(_ctx.$slots, "button-content", {}, () => [
createTextVNode(toDisplayString(unref(props).text), 1)
], true)
]),
_: 3
}, 8, ["id", "variant", "size", "class", "disabled", "type", "aria-label", "aria-expanded", "aria-haspopup", "href", "to"]),
unref(props).split ? (openBlock(), createBlock(_sfc_main$2, {
key: 0,
id: unref(computedId) + "-split",
ref: "_button",
variant: unref(props).variant,
size: unref(props).size,
disabled: unref(props).disabled,
class: normalizeClass([[unref(props).toggleClass, { show: unref(showRef) }], "dropdown-toggle-split dropdown-toggle"]),
"aria-expanded": unref(showRef),
"aria-haspopup": "menu",
onClick: onButtonClick
}, {
default: withCtx(() => [
createElementVNode("span", _hoisted_1, [
renderSlot(_ctx.$slots, "toggle-text", {}, () => [
createTextVNode(toDisplayString(unref(props).toggleText), 1)
], true)
])
]),
_: 3
}, 8, ["id", "variant", "size", "disabled", "class", "aria-expanded"])) : createCommentVNode("", true),
createVNode(_sfc_main$3, {
to: unref(props).teleportTo,
disabled: !unref(props).teleportTo || unref(props).teleportDisabled
}, {
default: withCtx(() => [
unref(renderRef) || unref(contentShowing) ? (openBlock(), createBlock(Transition, mergeProps({ key: 0 }, unref(transitionProps), {
appear: modelValue.value || unref(props).visible
}), {
default: withCtx(() => [
withDirectives(createElementVNode("ul", {
id: unref(computedId) + "-menu",
ref: "_floating",
style: normalizeStyle([unref(floatingStyles), sizeStyles.value]),
class: normalizeClass(["dropdown-menu overflow-auto", [unref(props).menuClass, computedMenuClasses.value]]),
"aria-labelledby": unref(computedId),
role: unref(props).role,
onClick: onClickInside
}, [
unref(contentShowing) ? renderSlot(_ctx.$slots, "default", {
key: 0,
hide: unref(hide),
show: unref(show),
visible: unref(showRef)
}, void 0, true) : createCommentVNode("", true)
], 14, _hoisted_2), [
[vShow, unref(showRef)]
])
]),
_: 3
}, 16, ["appear"])) : createCommentVNode("", true)
]),
_: 3
}, 8, ["to", "disabled"])
]),
_: 3
}, 8, ["skip", "class", "role"]);
};
}
});
const BDropdown = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-5ca1e58b"]]);
export {
BDropdown as B
};
//# sourceMappingURL=BDropdown-Csgw4gsr.mjs.map