"use strict";
const vue = require("vue");
const keys = require("./keys-D70E9HED.js");
const classes = require("./classes-DA6TfAZg.js");
const index = require("./index-C_bsiScj.js");
const functions = require("./functions-fuN3cbNp.js");
const index$1 = require("./index-JJEBhaXq.js");
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 = vue.ref(initialShow);
  const renderRef = vue.ref(initialShow);
  const renderBackdropRef = vue.ref(initialShow);
  let isCountdown = typeof modelValue.value !== "boolean";
  vue.watch(modelValue, () => {
    isCountdown = typeof modelValue.value !== "boolean";
    if (noAction) {
      noAction = false;
      return;
    }
    if (modelValue.value) {
      show();
    } else {
      hide("modelValue", true);
    }
  });
  const localNoAnimation = vue.ref(initialShow);
  const localTemporaryHide = vue.ref(false);
  const computedNoAnimation = vue.computed(
    () => props.noAnimation || props.noFade || localNoAnimation.value || false
  );
  let isMounted = false;
  vue.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();
    }
  });
  vue.watch(
    () => props.visible,
    (newval) => {
      localNoAnimation.value = true;
      vue.nextTick(() => {
        if (newval) isVisible.value = true;
        if (newval) {
          show();
        } else {
          hide("visible-prop", true);
        }
      });
    }
  );
  vue.watch(
    () => props.show,
    (newval) => {
      if (newval) {
        show();
      } else {
        hide("show-prop", true);
      }
    }
  );
  index.useEventListener(element, "bv-toggle", () => {
    modelValue.value = !modelValue.value;
  });
  const buildTriggerableEvent = (type, opts = {}) => new classes.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;
        vue.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;
          vue.nextTick(() => {
            modelValue.value = true;
          });
        }
        return;
      }
      showTimeout = setTimeout(
        () => {
          if (!isMounted) return;
          showTimeout = void 0;
          showRef.value = true;
          options.showFn?.();
          if (!modelValue.value) {
            noAction = true;
            vue.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) {
        vue.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 = index$1.useThrottleFn((a) => hide(a), 500);
  const throttleShow = index$1.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 = vue.inject(keys.showHideRegistryKey, null)?.register({
    id: computedId.value,
    toggle,
    show,
    hide,
    value: vue.readonly(showRef),
    registerTrigger,
    unregisterTrigger,
    component: vue.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);
  };
  vue.watch(modelValue, () => {
    triggerRegistry.forEach((t) => {
      checkVisibility(t.el);
    });
  });
  vue.watch(computedId, (newId, oldId) => {
    appRegistry?.updateId(newId, oldId);
  });
  vue.onBeforeUnmount(() => {
    appRegistry?.unregister();
    triggerRegistry.forEach((t) => {
      t.el.removeEventListener(t.trigger, triggerToggle);
    });
  });
  vue.onUnmounted(() => {
    isMounted = false;
    clearTimeout(showTimeout);
    clearTimeout(hideTimeout);
    showTimeout = void 0;
    hideTimeout = void 0;
  });
  const lazyLoadCompleted = vue.ref(false);
  const markLazyLoadCompleted = () => {
    if (props.lazy === true) lazyLoadCompleted.value = true;
  };
  const isLeaving = vue.ref(false);
  const isActive = vue.ref(initialShow);
  const isVisible = vue.ref(initialShow);
  const onBeforeEnter = [
    ...[
      options.transitionProps?.onBeforeEnter ?? functions.noop,
      props.transitionProps?.onBeforeEnter ?? functions.noop
    ].flat(),
    () => {
      isActive.value = true;
    }
  ];
  const onEnter = [
    () => {
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          isVisible.value = true;
        });
      });
    },
    ...[options.transitionProps?.onEnter ?? functions.noop, props.transitionProps?.onEnter ?? functions.noop].flat()
  ];
  const onAfterEnter = [
    markLazyLoadCompleted,
    ...[
      options.transitionProps?.onAfterEnter ?? functions.noop,
      props.transitionProps?.onAfterEnter ?? functions.noop
    ].flat(),
    () => {
      if (localNoAnimation.value) {
        requestAnimationFrame(() => {
          localNoAnimation.value = false;
        });
      }
      if (localTemporaryHide.value) {
        localTemporaryHide.value = false;
      }
      requestAnimationFrame(() => {
        trapActive.value = true;
        vue.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 ?? functions.noop,
      props.transitionProps?.onBeforeLeave ?? functions.noop
    ].flat(),
    () => {
      trapActive.value = false;
    }
  ];
  const onLeave = [
    () => {
      isVisible.value = false;
    },
    ...[options.transitionProps?.onLeave ?? functions.noop, props.transitionProps?.onLeave ?? functions.noop].flat()
  ];
  const onAfterLeave = [
    () => {
      emit("hidden", buildTriggerableEvent("hidden", { trigger: leaveTrigger, cancelable: false }));
    },
    ...[
      options.transitionProps?.onAfterLeave ?? functions.noop,
      props.transitionProps?.onAfterLeave ?? functions.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 = vue.computed(
    () => localTemporaryHide.value === true || isActive.value === true || props.lazy === false || props.lazy === true && lazyLoadCompleted.value === true && props.unmountLazy === false
  );
  const trapActive = vue.ref(false);
  const backdropVisible = vue.ref(false);
  const backdropReady = vue.ref(false);
  const transitionFunctions = {
    ...options.transitionProps,
    onBeforeEnter,
    onEnter,
    onAfterEnter,
    onBeforeLeave,
    onLeave,
    onAfterLeave
  };
  return {
    showRef: vue.readonly(showRef),
    renderRef: vue.readonly(renderRef),
    renderBackdropRef: vue.readonly(renderBackdropRef),
    isVisible: vue.readonly(isVisible),
    isActive: vue.readonly(isActive),
    trapActive: vue.readonly(trapActive),
    show,
    hide,
    toggle,
    throttleHide,
    throttleShow,
    buildTriggerableEvent,
    computedNoAnimation,
    localNoAnimation: vue.readonly(localNoAnimation),
    setLocalNoAnimation: (value) => {
      localNoAnimation.value = value;
    },
    localTemporaryHide: vue.readonly(localTemporaryHide),
    setLocalTemporaryHide: (value) => {
      localTemporaryHide.value = value;
    },
    isLeaving: vue.readonly(isLeaving),
    transitionProps: {
      ...fadeBaseTransitionProps,
      ...props.transitionProps,
      ...transitionFunctions
    },
    lazyLoadCompleted: vue.readonly(lazyLoadCompleted),
    markLazyLoadCompleted,
    contentShowing,
    backdropReady: vue.readonly(backdropReady),
    backdropVisible: vue.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;
        });
      }
    }
  };
};
exports.useShowHide = useShowHide;
//# sourceMappingURL=useShowHide-b1MKf6Ye.js.map
