<script setup>
import { useMediaQuery } from "@vueuse/core";
import { computed, ref, useAttrs, useSlots } from "vue";
import {
  Dialog,
  DialogClose,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogScrollContent,
  DialogTitle,
  DialogTrigger
} from "./ui/dialog";
import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger
} from "./ui/drawer";
defineOptions({
  name: "ResponsiveModal",
  inheritAttrs: false
});
const props = defineProps({
  open: { type: Boolean, required: false },
  defaultOpen: { type: Boolean, required: false, default: false },
  breakpoint: { type: String, required: false, default: "(min-width: 640px)" },
  showCloseButton: { type: Boolean, required: false, default: true },
  dismissible: { type: Boolean, required: false, default: true },
  contentWidth: { type: String, required: false }
});
const emit = defineEmits(["update:open", "after-close"]);
const attrs = useAttrs();
const slots = useSlots();
const uncontrolledOpen = ref(props.defaultOpen);
const isDesktop = useMediaQuery(props.breakpoint);
const desktopComponents = {
  Root: Dialog,
  Trigger: DialogTrigger,
  Content: DialogScrollContent,
  Header: DialogHeader,
  Title: DialogTitle,
  Description: DialogDescription,
  Footer: DialogFooter,
  Close: DialogClose
};
const mobileComponents = {
  Root: Drawer,
  Trigger: DrawerTrigger,
  Content: DrawerContent,
  Header: DrawerHeader,
  Title: DrawerTitle,
  Description: DrawerDescription,
  Footer: DrawerFooter,
  Close: DrawerClose
};
const modalComponents = computed(() => isDesktop.value ? desktopComponents : mobileComponents);
const hasTrigger = computed(() => slots.trigger !== void 0);
const hasTitle = computed(() => slots.title !== void 0);
const hasDescription = computed(() => slots.description !== void 0);
const hasHeader = computed(() => hasTitle.value || hasDescription.value);
const hasFooter = computed(() => slots.footer !== void 0);
const open = computed({
  get() {
    return props.open ?? uncontrolledOpen.value;
  },
  set(value) {
    if (props.open === void 0) {
      uncontrolledOpen.value = value;
    }
    emit("update:open", value);
  }
});
function close() {
  open.value = false;
}
</script>

<template>
  <ClientOnly>
    <component
      :is="modalComponents.Root"
      v-model:open="open"
      :dismissible="props.dismissible"
    >
      <component
        :is="modalComponents.Trigger"
        v-if="hasTrigger"
        as-child
      >
        <slot
          name="trigger"
          v-bind="{ close, isDesktop }"
        />
      </component>

      <component
        :is="modalComponents.Content"
        v-bind="attrs"
        :show-close-button="props.showCloseButton"
        :content-width="props.contentWidth"
        @after-close="emit('after-close')"
      >
        <component
          :is="modalComponents.Header"
          v-if="hasHeader"
        >
          <component
            :is="modalComponents.Title"
            v-if="hasTitle"
          >
            <slot
              name="title"
              v-bind="{ close, isDesktop }"
            />
          </component>

          <component
            :is="modalComponents.Description"
            v-if="hasDescription"
          >
            <slot
              name="description"
              v-bind="{ close, isDesktop }"
            />
          </component>
        </component>

        <component
          :is="modalComponents.Description"
          v-if="!hasDescription"
          class="sr-only"
        />

        <slot v-bind="{ close, isDesktop }" />

        <component
          :is="modalComponents.Footer"
          v-if="hasFooter"
        >
          <slot
            name="footer"
            v-bind="{ close, isDesktop }"
          />
        </component>
      </component>
    </component>
  </ClientOnly>
</template>
