UNPKG

bootstrap-vue-next

Version:

Seamless integration of Vue 3, Bootstrap 5, and TypeScript for modern, type-safe UI development

398 lines (397 loc) 13.6 kB
import { a as buttonGroupKey, p as inputGroupKey, u as dropdownInjectionKey } from "./keys-CQKrwmvN.mjs"; import { a as onClickOutside, o as onKeyStroke, z as useToNumber } from "./dist-B10a-gZ8.mjs"; import { i as getSafeDocument } from "./dom-AhkaSoh8.mjs"; import { t as useDefaults } from "./useDefaults-BKgBaqOV.mjs"; import { t as useId$1 } from "./useId-BKZFSYm8.mjs"; import { t as useShowHide } from "./useShowHide-yAK5dhPT.mjs"; import { t as BButton_default } from "./BButton-BRvIFnRm.mjs"; import { t as ConditionalTeleport_default } from "./ConditionalTeleport-BNsziElf.mjs"; import { a as flip, d as size, i as autoUpdate, l as offset, n as useFloating, u as shift } from "./floating-ui.vue-CAMaNcqI.mjs"; import { t as ConditionalWrapper_default } from "./ConditionalWrapper-D9ovtbHB.mjs"; import { a as resolveBootstrapCaret, n as isBoundary, r as isRootBoundary } from "./floatingUi-DHMrP__c.mjs"; import { t as getElement } from "./getElement-0_htvrFw.mjs"; import { Transition, computed, createBlock, createCommentVNode, createElementVNode, createTextVNode, createVNode, defineComponent, inject, mergeModels, mergeProps, nextTick, normalizeClass, normalizeStyle, openBlock, provide, readonly, ref, renderSlot, toDisplayString, toRef, unref, useModel, useTemplateRef, vShow, watch, withCtx, withDirectives } from "vue"; //#region src/components/BDropdown/BDropdown.vue?vue&type=script&setup=true&lang.ts var _hoisted_1 = { class: "visually-hidden" }; var _hoisted_2 = [ "id", "aria-labelledby", "role" ]; //#endregion //#region src/components/BDropdown/BDropdown.vue var BDropdown_default = /* @__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 }, icon: { type: Boolean, default: false }, 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([ "split-click", "hide", "hide-prevented", "hidden", "show", "show-prevented", "shown", "toggle", "toggle-prevented" ], ["update:modelValue"]), setup(__props, { expose: __expose, emit: __emit }) { const props = useDefaults(__props, "BDropdown"); const emit = __emit; const computedId = useId$1(() => props.id, "dropdown"); const modelValue = useModel(__props, "modelValue"); const inInputGroup = inject(inputGroupKey, false); const inButtonGroup = inject(buttonGroupKey, false); const offsetToNumber = useToNumber(computed(() => typeof props.offset === "string" || typeof props.offset === "number" ? props.offset : NaN)); const floatingElement = 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 referenceElement = computed(() => !props.split ? splitButton.value : button.value); let cleanup; const { showRef, renderRef, hide, show, toggle, computedNoAnimation, transitionProps, contentShowing, isVisible, isActive } = useShowHide(modelValue, props, emit, referenceElement, computedId, { showFn: () => { update(); nextTick(() => { cleanup = autoUpdate(referenceElement.value, floatingElement.value, update, { animationFrame: false }); }); }, hideFn: () => { if (cleanup) { cleanup(); cleanup = void 0; } } }); const computedMenuClasses = computed(() => [{ show: isVisible.value, fade: !computedNoAnimation.value }]); onKeyStroke("Escape", () => { hide(); getElement(referenceElement.value)?.focus(); }, { target: referenceElement }); onKeyStroke("Escape", () => { hide(); getElement(referenceElement.value)?.focus(); }, { target: floatingElement, passive: true }); const keynav = (e, v) => { if (floatingElement.value?.contains(e.target?.closest("form"))) return; if (/input|select|option|textarea|form/i.test(e.target?.tagName)) return; e.preventDefault(); if (!showRef.value) { show(); const loop = setInterval(() => { if (isVisible.value) { clearInterval(loop); nextTick(() => keynav(e, v)); } }, 16); return; } const list = floatingElement.value?.querySelectorAll(".dropdown-item:not(.disabled):not(:disabled)"); const doc = getSafeDocument(); if (!list || !doc) return; if (floatingElement.value?.contains(doc.activeElement)) { const active = floatingElement.value.querySelector(".dropdown-item:focus"); const index = Array.prototype.indexOf.call(list, active) + v; if (index >= 0 && index < list?.length) list[index]?.focus(); } else list[v === -1 ? list.length - 1 : 0]?.focus(); }; onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: referenceElement }); onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: referenceElement }); onKeyStroke("ArrowUp", (e) => keynav(e, -1), { target: floatingElement }); onKeyStroke("ArrowDown", (e) => keynav(e, 1), { target: floatingElement }); const sizeStyles = ref({}); const { update, floatingStyles } = useFloating(referenceElement, floatingElement, { placement: () => props.placement, middleware: computed(() => { if (props.floatingMiddleware !== void 0) return props.floatingMiddleware; const arr = [offset(typeof props.offset === "string" || typeof props.offset === "number" ? offsetToNumber.value : props.offset)]; 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 }) { sizeStyles.value = { "--bv-floating-max-height": availableHeight >= (floatingElement.value?.scrollHeight ?? 0) ? void 0 : availableHeight ? `${Math.max(0, availableHeight)}px` : void 0, "--bv-floating-max-width": availableWidth >= (floatingElement.value?.scrollWidth ?? 0) ? void 0 : availableWidth ? `${Math.max(0, availableWidth)}px` : void 0 }; } })); return arr; }), strategy: toRef(() => props.strategy) }); const inButtonGroupAttributes = inButtonGroup ? { class: "btn-group", role: "group" } : void 0; const computedClasses = computed(() => [ inButtonGroupAttributes?.class, props.wrapperClass, { "btn-group": !props.wrapperClass && props.split, [`drop${resolveBootstrapCaret(props.placement)}`]: !props.wrapperClass, "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("split-click", event); return; } onButtonClick(); }; onClickOutside(floatingElement, () => { 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: readonly(showRef), isNav: toRef(() => props.isNav) }); return (_ctx, _cache) => { return openBlock(), createBlock(ConditionalWrapper_default, { skip: unref(inInputGroup) || unref(props).noWrapper, class: normalizeClass(computedClasses.value), role: unref(inButtonGroupAttributes)?.role }, { default: withCtx(() => [ createVNode(BButton_default, { 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, icon: unref(props).icon, 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)])]), _: 3 }, 8, [ "id", "variant", "size", "class", "disabled", "type", "aria-label", "aria-expanded", "aria-haspopup", "href", "icon", "to" ]), unref(props).split ? (openBlock(), createBlock(BButton_default, { 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)])])]), _: 3 }, 8, [ "id", "variant", "size", "disabled", "class", "aria-expanded" ])) : createCommentVNode("", true), createVNode(ConditionalTeleport_default, { 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, { display: unref(showRef) || unref(isActive) ? "block" : "none" } ]), class: normalizeClass(["dropdown-menu overflow-auto b-floating-size", [unref(props).menuClass, computedMenuClasses.value]]), "aria-labelledby": unref(computedId), role: unref(props).role, onClick: onClickInside }, [unref(contentShowing) ? renderSlot(_ctx.$slots, "default", { key: 0, id: unref(computedId), hide: unref(hide), show: unref(show), visible: unref(showRef), click: onClickInside, toggle: onButtonClick, active: unref(showRef) }) : createCommentVNode("", true)], 14, _hoisted_2), [[vShow, unref(showRef)]])]), _: 3 }, 16, ["appear"])) : createCommentVNode("", true)]), _: 3 }, 8, ["to", "disabled"]) ]), _: 3 }, 8, [ "skip", "class", "role" ]); }; } }); //#endregion export { BDropdown_default as t }; //# sourceMappingURL=BDropdown-DAHnN54Z.mjs.map