UNPKG

bootstrap-vue-next

Version:

BootstrapVueNext is an early and lovely component library for Vue 3 & Nuxt 3 based on Bootstrap 5 and Typescript.

458 lines (457 loc) 13.5 kB
import { ref, watch, computed, onMounted, nextTick, inject, getCurrentInstance, readonly, onBeforeUnmount, onUnmounted } from "vue"; import { s as showHideRegistryKey } from "./keys-BLeKMItg.mjs"; import { a as BvTriggerableEvent } from "./classes-BW_GpXTu.mjs"; import { h as useEventListener } from "./index-CNe4dKrr.mjs"; import { a as useThrottleFn } from "./index-BkgVGYcq.mjs"; const fadeBaseTransitionProps = { name: "fade", enterActiveClass: "", enterFromClass: "showing", enterToClass: "", leaveActiveClass: "", leaveFromClass: "", leaveToClass: "showing", css: true }; const 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) 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, void 0)?.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 = (el) => { options.transitionProps?.onBeforeEnter?.(el); props.transitionProps?.onBeforeEnter?.(el); isActive.value = true; }; const onEnter = (el) => { requestAnimationFrame(() => { requestAnimationFrame(() => { isVisible.value = true; }); }); options.transitionProps?.onEnter?.(el); props.transitionProps?.onEnter?.(el); }; const onAfterEnter = (el) => { markLazyLoadCompleted(); options.transitionProps?.onAfterEnter?.(el); props.transitionProps?.onAfterEnter?.(el); 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 = (el) => { if (!isLeaving.value) isLeaving.value = true; options.transitionProps?.onBeforeLeave?.(el); props.transitionProps?.onBeforeLeave?.(el); trapActive.value = false; }; const onLeave = (el) => { isVisible.value = false; options.transitionProps?.onLeave?.(el); props.transitionProps?.onLeave?.(el); }; const onAfterLeave = (el) => { emit("hidden", buildTriggerableEvent("hidden", { trigger: leaveTrigger, cancelable: false })); options.transitionProps?.onAfterLeave?.(el); props.transitionProps?.onAfterLeave?.(el); 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, renderRef, renderBackdropRef, isVisible, isActive, trapActive, show, hide, toggle, throttleHide, throttleShow, buildTriggerableEvent, computedNoAnimation, localNoAnimation, localTemporaryHide, isLeaving, transitionProps: { ...fadeBaseTransitionProps, ...props.transitionProps, ...transitionFunctions }, lazyLoadCompleted, markLazyLoadCompleted, contentShowing, backdropReady, 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; }); } } }; }; export { useShowHide as u }; //# sourceMappingURL=useShowHide-K2QIdPKK.mjs.map