UNPKG

bootstrap-vue-next

Version:

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

430 lines (429 loc) 12.9 kB
import { x as showHideRegistryKey } from "./keys-CQKrwmvN.mjs"; import { I as useThrottleFn, p as useEventListener } from "./dist-Dn5blevd.mjs"; import { r as BvTriggerableEvent } from "./classes-B0E5Y78Y.mjs"; import { t as noop } from "./functions-BcMenQqL.mjs"; import { computed, getCurrentInstance, inject, nextTick, onBeforeUnmount, onMounted, onUnmounted, readonly, ref, watch } from "vue"; //#region src/composables/useShowHide.ts var fadeBaseTransitionProps = { name: "fade", enterActiveClass: "", enterFromClass: "showing", enterToClass: "", leaveActiveClass: "", leaveFromClass: "", leaveToClass: "showing", css: true }; var useShowHide = (modelValue, props, emit, element, computedId, options = { transitionProps: {}, showFn: () => {}, hideFn: () => {} }) => { let noAction = false; const initialShow = !!modelValue.value && !props.initialAnimation || props.visible || false; const showRef = ref(initialShow); const renderRef = ref(initialShow); const renderBackdropRef = ref(initialShow); let isCountdown = typeof modelValue.value !== "boolean"; watch(modelValue, () => { isCountdown = typeof modelValue.value !== "boolean"; if (noAction) { noAction = false; return; } if (modelValue.value) show(); else hide("modelValue", true); }); const localNoAnimation = ref(initialShow); const localTemporaryHide = ref(false); const computedNoAnimation = computed(() => props.noAnimation || props.noFade || localNoAnimation.value || false); let isMounted = false; onMounted(() => { isMounted = true; if (!props.show && initialShow) { const event = buildTriggerableEvent("show", { cancelable: true }); emit("show", event); if (event.defaultPrevented) { emit("show-prevented", buildTriggerableEvent("show-prevented")); return; } localNoAnimation.value = true; if (!modelValue.value) { noAction = true; modelValue.value = true; } renderRef.value = true; renderBackdropRef.value = true; isVisible.value = true; backdropVisible.value = true; backdropReady.value = true; showRef.value = true; options.showFn?.(); } else if (props.show || !!modelValue.value && props.initialAnimation) show(); }); watch(() => props.visible, (newval) => { localNoAnimation.value = true; nextTick(() => { if (newval) isVisible.value = true; if (newval) show(); else hide("visible-prop", true); }); }); watch(() => props.show, (newval) => { if (newval) show(); else hide("show-prop", true); }); useEventListener(element, "bv-toggle", () => { modelValue.value = !modelValue.value; }); const buildTriggerableEvent = (type, opts = {}) => new BvTriggerableEvent(type, { cancelable: false, target: element?.value || null, relatedTarget: null, trigger: null, ...opts, componentId: computedId?.value }); let showTimeout; let hideTimeout; let _Resolve; let _Promise; let _resolveOnHide; const show = (resolveOnHide = false) => { if (showRef.value && !hideTimeout && !_Promise) return Promise.resolve(true); _resolveOnHide = resolveOnHide; if (showRef.value && !hideTimeout && _Promise) return _Promise; _Promise = new Promise((resolve) => { _Resolve = resolve; }); const event = buildTriggerableEvent("show", { cancelable: true }); emit("show", event); if (event.defaultPrevented) { emit("show-prevented", buildTriggerableEvent("show-prevented")); if (isVisible.value) isVisible.value = false; if (modelValue.value && !isCountdown) { noAction = true; nextTick(() => { modelValue.value = false; }); } _Resolve?.("show-prevented"); return _Promise; } if (hideTimeout) { clearTimeout(hideTimeout); hideTimeout = void 0; } renderRef.value = true; renderBackdropRef.value = true; requestAnimationFrame(() => { if (localNoAnimation.value || props.delay === void 0) { if (!isMounted) return; showTimeout = void 0; showRef.value = true; options.showFn?.(); if (!modelValue.value) { noAction = true; nextTick(() => { modelValue.value = true; }); } return; } showTimeout = setTimeout(() => { if (!isMounted) return; showTimeout = void 0; showRef.value = true; options.showFn?.(); if (!modelValue.value) { noAction = true; nextTick(() => { modelValue.value = true; }); } }, typeof props.delay === "number" ? props.delay : props.delay?.show || 0); }); return _Promise; }; let leaveTrigger; const hide = (trigger, noTriggerEmit) => { if (!showRef.value && !showTimeout && !renderRef.value) return Promise.resolve(""); if (!_Promise) _Promise = new Promise((resolve) => { _Resolve = resolve; }); if (typeof trigger !== "string") trigger = void 0; leaveTrigger = trigger; const event = buildTriggerableEvent("hide", { cancelable: true, trigger }); const event2 = buildTriggerableEvent(trigger || "ignore", { cancelable: true, trigger }); if (trigger === "backdrop" && props.noCloseOnBackdrop || trigger === "esc" && props.noCloseOnEsc) { emit("hide-prevented", buildTriggerableEvent("hide-prevented", { trigger })); _Resolve?.("hide-prevented"); return _Promise; } if (showTimeout) { clearTimeout(showTimeout); showTimeout = void 0; } if (trigger && !noTriggerEmit) emit(trigger, event2); emit("hide", event); if (event.defaultPrevented || event2.defaultPrevented) { emit("hide-prevented", buildTriggerableEvent("hide-prevented", { trigger })); if (!modelValue.value) nextTick(() => { noAction = true; modelValue.value = true; }); _Resolve?.("hide-prevented"); return _Promise; } trapActive.value = false; if (showTimeout) { clearTimeout(showTimeout); showTimeout = void 0; if (!localTemporaryHide.value) renderRef.value = false; renderBackdropRef.value = false; } hideTimeout = setTimeout(() => { if (!isMounted) return; hideTimeout = void 0; isLeaving.value = true; showRef.value = false; options.hideFn?.(); if (modelValue.value) { noAction = true; modelValue.value = isCountdown ? 0 : false; } }, localNoAnimation.value ? 0 : typeof props.delay === "number" ? props.delay : props.delay?.hide || 0); return _Promise; }; const throttleHide = useThrottleFn((a) => hide(a), 500); const throttleShow = useThrottleFn(() => show(), 500); const toggle = (resolveOnHide = false) => { const e = buildTriggerableEvent("toggle", { cancelable: true }); emit("toggle", e); if (e.defaultPrevented) { emit("toggle-prevented", buildTriggerableEvent("toggle-prevented")); return Promise.resolve("toggle-prevented"); } if (showRef.value) return hide("toggle-function", true); return show(resolveOnHide); }; const triggerToggle = () => { const e = buildTriggerableEvent("toggle", { cancelable: true }); emit("toggle", e); if (e.defaultPrevented) { emit("toggle-prevented", buildTriggerableEvent("toggle-prevented")); return; } if (showRef.value) hide("toggle-trigger", true); else show(); }; const triggerRegistry = []; const registerTrigger = (trigger, el) => { triggerRegistry.push({ trigger, el }); el.addEventListener(trigger, triggerToggle); checkVisibility(el); }; const unregisterTrigger = (trigger, el, clean = true) => { const idx = triggerRegistry.findIndex((t) => t?.trigger === trigger && t.el === el); if (idx > -1) { triggerRegistry.splice(idx, 1); el.removeEventListener(trigger, triggerToggle); if (clean) { el.removeAttribute("aria-expanded"); el.classList.remove("collapsed"); el.classList.remove("not-collapsed"); } } }; const appRegistry = inject(showHideRegistryKey, null)?.register({ id: computedId.value, toggle, show, hide, value: readonly(showRef), registerTrigger, unregisterTrigger, component: getCurrentInstance() }); const checkVisibility = (el) => { el.setAttribute("aria-expanded", modelValue.value ? "true" : "false"); el.classList.toggle("collapsed", !modelValue.value); el.classList.toggle("not-collapsed", !!modelValue.value); }; watch(modelValue, () => { triggerRegistry.forEach((t) => { checkVisibility(t.el); }); }); watch(computedId, (newId, oldId) => { appRegistry?.updateId(newId, oldId); }); onBeforeUnmount(() => { appRegistry?.unregister(); triggerRegistry.forEach((t) => { t.el.removeEventListener(t.trigger, triggerToggle); }); }); onUnmounted(() => { isMounted = false; clearTimeout(showTimeout); clearTimeout(hideTimeout); showTimeout = void 0; hideTimeout = void 0; }); const lazyLoadCompleted = ref(false); const markLazyLoadCompleted = () => { if (props.lazy === true) lazyLoadCompleted.value = true; }; const isLeaving = ref(false); const isActive = ref(initialShow); const isVisible = ref(initialShow); const onBeforeEnter = [...[options.transitionProps?.onBeforeEnter ?? noop, props.transitionProps?.onBeforeEnter ?? noop].flat(), () => { isActive.value = true; }]; const onEnter = [() => { requestAnimationFrame(() => { requestAnimationFrame(() => { isVisible.value = true; }); }); }, ...[options.transitionProps?.onEnter ?? noop, props.transitionProps?.onEnter ?? noop].flat()]; const onAfterEnter = [ markLazyLoadCompleted, ...[options.transitionProps?.onAfterEnter ?? noop, props.transitionProps?.onAfterEnter ?? noop].flat(), () => { if (localNoAnimation.value) requestAnimationFrame(() => { localNoAnimation.value = false; }); if (localTemporaryHide.value) localTemporaryHide.value = false; requestAnimationFrame(() => { trapActive.value = true; nextTick(() => { emit("shown", buildTriggerableEvent("shown", { cancelable: false })); }); }); if (!_resolveOnHide) { _Resolve?.(true); _Promise = void 0; _Resolve = void 0; } } ]; const onBeforeLeave = [ () => { if (!isLeaving.value) isLeaving.value = true; }, ...[options.transitionProps?.onBeforeLeave ?? noop, props.transitionProps?.onBeforeLeave ?? noop].flat(), () => { trapActive.value = false; } ]; const onLeave = [() => { isVisible.value = false; }, ...[options.transitionProps?.onLeave ?? noop, props.transitionProps?.onLeave ?? noop].flat()]; const onAfterLeave = [ () => { emit("hidden", buildTriggerableEvent("hidden", { trigger: leaveTrigger, cancelable: false })); }, ...[options.transitionProps?.onAfterLeave ?? noop, props.transitionProps?.onAfterLeave ?? noop].flat(), () => { isLeaving.value = false; isActive.value = false; if (localNoAnimation.value) requestAnimationFrame(() => { localNoAnimation.value = false; }); requestAnimationFrame(() => { if (!localTemporaryHide.value) renderRef.value = false; }); _Resolve?.(leaveTrigger || ""); _Promise = void 0; _Resolve = void 0; leaveTrigger = void 0; } ]; const contentShowing = computed(() => localTemporaryHide.value === true || isActive.value === true || props.lazy === false || props.lazy === true && lazyLoadCompleted.value === true && props.unmountLazy === false); const trapActive = ref(false); const backdropVisible = ref(false); const backdropReady = ref(false); const transitionFunctions = { ...options.transitionProps, onBeforeEnter, onEnter, onAfterEnter, onBeforeLeave, onLeave, onAfterLeave }; return { showRef: readonly(showRef), renderRef: readonly(renderRef), renderBackdropRef: readonly(renderBackdropRef), isVisible: readonly(isVisible), isActive: readonly(isActive), trapActive: readonly(trapActive), show, hide, toggle, throttleHide, throttleShow, buildTriggerableEvent, computedNoAnimation, localNoAnimation: readonly(localNoAnimation), setLocalNoAnimation: (value) => { localNoAnimation.value = value; }, localTemporaryHide: readonly(localTemporaryHide), setLocalTemporaryHide: (value) => { localTemporaryHide.value = value; }, isLeaving: readonly(isLeaving), transitionProps: { ...fadeBaseTransitionProps, ...props.transitionProps, ...transitionFunctions }, lazyLoadCompleted: readonly(lazyLoadCompleted), markLazyLoadCompleted, contentShowing, backdropReady: readonly(backdropReady), backdropVisible: readonly(backdropVisible), backdropTransitionProps: { ...fadeBaseTransitionProps, onBeforeEnter: () => { requestAnimationFrame(() => { requestAnimationFrame(() => { backdropVisible.value = true; }); }); backdropReady.value = false; }, onAfterEnter: () => { backdropReady.value = true; }, onBeforeLeave: () => { backdropVisible.value = false; }, onAfterLeave: () => { backdropReady.value = false; requestAnimationFrame(() => { renderBackdropRef.value = false; }); } } }; }; //#endregion export { useShowHide as t }; //# sourceMappingURL=useShowHide-IPyuuPL0.mjs.map