<script setup lang="ts">
import {ChevronDownIcon, ChevronUpIcon} from '@heroicons/vue/24/outline';
import {vOnClickOutside} from '@vueuse/components';
import {useElementBounding, useEventListener} from '@vueuse/core';
import {computed, ref} from 'vue';

interface Props {
  inline?: boolean;
  autoClose?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  inline: false,
  autoClose: true
})

const isOpen = ref(false);
const root = ref<HTMLElement | null>(null);
const floating = ref<HTMLElement | null>(null);

const { left, bottom, width } = useElementBounding(root);

const floatingStyle = computed(() => ({
  left: `${left.value}px`,
  top: `${bottom.value}px`,
  minWidth: `${width.value}px`,
}));

const doAutoClose = () => {
  if (props.autoClose) {
    isOpen.value = false;
  }
}

useEventListener('keyup', e => {
    if (e.key === 'Escape') {
      doAutoClose();
    }
});
</script>

<template>
    <div ref="root" class="dropdown" :class="{'dropdown-open': isOpen, 'dropdown-close': !isOpen}" v-on-click-outside="[doAutoClose, { ignore: [floating] }]">
        <button @click="isOpen = !isOpen" class="cursor-pointer">
            <Transition
                enter-active-class="transition-transform"
                enter-from-class="rotate-180"
                leave-active-class="hidden"
                leave-to-class="rotate-180">
                <ChevronDownIcon v-if="!isOpen" class="chevron" />
                <ChevronUpIcon v-else class="chevron" />
            </Transition>
          <slot name="button" />
        </button>

        <Transition
            enter-active-class="transition-opacity"
            enter-from-class="opacity-0"
            leave-from-class="transition-opacity"
            leave-to-class="opacity-0">
            <div v-if="inline && isOpen">
              <slot />
            </div>
        </Transition>
      
        <Teleport to="body">
          <Transition
              enter-active-class="transition-opacity"
              enter-from-class="opacity-0"
              leave-from-class="transition-opacity"
              leave-to-class="opacity-0">
            <div v-if="!inline && isOpen" ref="floating" class="dropdown-floating" :style="floatingStyle">
              <div class="divide-y rounded-b-md">
                <slot />
              </div>
            </div>
          </Transition>
        </Teleport>
    </div>
</template>

<style scoped>
@reference "@/style.css";

.chevron {
    @apply w-4 h-4 me-1;
}

.dropdown-floating {
    @apply fixed z-10;
}

.dropdown-floating > div {
    @apply bg-slate-800 rounded-b-md shadow-lg;
}
</style>
