<script setup>
import { reactiveOmit } from "@vueuse/core";
import {
  DialogClose,
  DialogContent,
  DialogPortal,
  useForwardPropsEmits
} from "reka-ui";
import { cn } from "../../../utils/cn";
import DialogOverlay from "./DialogOverlay.vue";
import { Icon } from "@iconify/vue";
import { onBeforeUnmount, shallowRef, watchEffect } from "vue";
defineOptions({
  inheritAttrs: false
});
const props = defineProps({
  forceMount: { type: Boolean, required: false },
  disableOutsidePointerEvents: { type: Boolean, required: false },
  asChild: { type: Boolean, required: false },
  as: { type: null, required: false },
  class: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
  showCloseButton: { type: Boolean, required: false, default: true }
});
const emit = defineEmits(["escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "openAutoFocus", "closeAutoFocus", "after-close"]);
const delegatedProps = reactiveOmit(props, "class");
const forwarded = useForwardPropsEmits(delegatedProps, emit);
const contentElement = shallowRef(null);
let closeFallbackTimer;
let hasEmittedAfterClose = false;
function isClosedContentTarget(target) {
  return target instanceof HTMLElement && target.dataset.state === "closed";
}
function clearCloseFallbackTimer() {
  if (closeFallbackTimer === void 0) {
    return;
  }
  window.clearTimeout(closeFallbackTimer);
  closeFallbackTimer = void 0;
}
function emitAfterClose() {
  if (hasEmittedAfterClose) {
    return;
  }
  hasEmittedAfterClose = true;
  clearCloseFallbackTimer();
  emit("after-close");
}
function parseDurationMs(value) {
  const normalizedValue = value.trim();
  if (normalizedValue.endsWith("ms")) {
    const duration = Number.parseFloat(normalizedValue.slice(0, -2));
    return Number.isFinite(duration) ? duration : 0;
  }
  if (normalizedValue.endsWith("s")) {
    const duration = Number.parseFloat(normalizedValue.slice(0, -1));
    return Number.isFinite(duration) ? duration * 1e3 : 0;
  }
  return 0;
}
function getLongestMotionMs(element) {
  const style = window.getComputedStyle(element);
  const animationDurations = style.animationDuration.split(",");
  const animationDelays = style.animationDelay.split(",");
  const transitionDurations = style.transitionDuration.split(",");
  const transitionDelays = style.transitionDelay.split(",");
  let longestMotionMs = 0;
  for (const [index, durationValue] of animationDurations.entries()) {
    const durationMs = parseDurationMs(durationValue);
    const delayMs = parseDurationMs(animationDelays[index] ?? animationDelays[0] ?? "0s");
    longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
  }
  for (const [index, durationValue] of transitionDurations.entries()) {
    const durationMs = parseDurationMs(durationValue);
    const delayMs = parseDurationMs(transitionDelays[index] ?? transitionDelays[0] ?? "0s");
    longestMotionMs = Math.max(longestMotionMs, durationMs + delayMs);
  }
  return longestMotionMs;
}
function syncCloseFallback() {
  const element = contentElement.value;
  clearCloseFallbackTimer();
  if (!element) {
    return;
  }
  if (element.dataset.state !== "closed") {
    hasEmittedAfterClose = false;
    return;
  }
  const motionMs = getLongestMotionMs(element);
  closeFallbackTimer = window.setTimeout(() => {
    emitAfterClose();
  }, motionMs > 0 ? motionMs : 0);
}
function handleCloseMotionEnd(event) {
  if (hasEmittedAfterClose || event.target !== event.currentTarget || !isClosedContentTarget(event.currentTarget)) {
    return;
  }
  emitAfterClose();
}
function setContentElement(target) {
  if (target instanceof HTMLElement) {
    contentElement.value = target;
    syncCloseFallback();
    return;
  }
  if (target && "$el" in target && target.$el instanceof HTMLElement) {
    contentElement.value = target.$el;
    syncCloseFallback();
    return;
  }
  contentElement.value = null;
  clearCloseFallbackTimer();
}
watchEffect((onCleanup) => {
  const element = contentElement.value;
  if (!element) {
    return;
  }
  const observer = new MutationObserver(() => {
    syncCloseFallback();
  });
  observer.observe(element, {
    attributes: true,
    attributeFilter: ["data-state"]
  });
  syncCloseFallback();
  onCleanup(() => {
    observer.disconnect();
  });
});
onBeforeUnmount(() => {
  clearCloseFallbackTimer();
});
</script>

<template>
  <DialogPortal>
    <DialogOverlay />
    <DialogContent
      :ref="setContentElement"
      data-slot="dialog-content"
      v-bind="{ ...$attrs, ...forwarded }"
      :class="
  cn(
    'bg-white data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-zinc-200 p-6 shadow-lg duration-200 sm:max-w-lg',
    props.class
  )
"
      @animationend="handleCloseMotionEnd"
      @transitionend="handleCloseMotionEnd"
    >
      <slot />

      <DialogClose
        v-if="showCloseButton"
        data-slot="dialog-close"
        class="data-[state=open]:bg-zinc-100 data-[state=open]:text-zinc-700 absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
      >
        <Icon icon="fluent:dismiss-20-filled" />
        <span class="sr-only">Close</span>
      </DialogClose>
    </DialogContent>
  </DialogPortal>
</template>
