<script setup lang="ts">
import { onClickOutside } from '@vueuse/core'

const props = withDefaults(
  defineProps<{
    open?: boolean
    persistent?: boolean
  }>(),
  {
    open: false,
    persistent: false
  }
)

const show = ref<boolean>(false)
watch(
  () => props.open,
  () => (show.value = props.open),
  { immediate: true }
)

const modal = ref<HTMLElement | null>(null)
const modalBox = ref(null)

const open = () => (show.value = true)
const close = (): Promise<boolean> => {
  return new Promise((resolve) => {
    modal.value?.addEventListener('transitionend', () => resolve(true))
    show.value = false
  })
}

const slotProps = { open, close }

if (!props.persistent) onClickOutside(modalBox, () => close())

const onEnter = (el: Element, done: () => void): void => {
  setTimeout(() => {
    el.classList.add('modal-open')
    done()
  })
}

const onLeave = (el: Element, done: () => void): void => {
  el.classList.remove('modal-open')
  el.addEventListener('transitionend', () => done())
}

defineExpose({ open, close })
</script>
<template>
  <slot name="activator" v-bind="slotProps"></slot>
  <Teleport to="body">
    <Transition @enter="onEnter" @leave="onLeave" appear>
      <div class="modal bg-neutral-800 bg-opacity-60" v-if="show" ref="modal">
        <div class="modal-box" ref="modalBox">
          <h3 class="text-lg font-bold" v-if="$slots.title"><slot name="title" /></h3>
          <p class="py-4">
            <slot v-bind="slotProps" />
          </p>
          <div class="modal-action">
            <slot name="actions" v-bind="slotProps">
              <button class="btn-sm btn" @click="close">Close</button>
            </slot>
          </div>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>
