UNPKG

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
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