<template>
  <Teleport to="body">
    <div
      v-if="visible"
      class="vm-ctx-menu vm-dialog-float"
      :style="{ left: `${x}px`, top: `${y}px` }"
      @click.stop
    >
      <button
        v-for="item in items"
        :key="item.key"
        type="button"
        class="vm-ctx-menu__item"
        :disabled="item.disabled"
        @click="onPick(item)"
      >
        {{ item.label }}
      </button>
    </div>
  </Teleport>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import type { CtxMenuItem } from '../../../../typings/admin/comm/crud'
defineOptions({ name: 'vm-context-menu' })

const props = defineProps<{
  items: CtxMenuItem[]
}>()

const emit = defineEmits<{
  select: [key: string]
}>()

const visible = ref(false)
const x = ref(0)
const y = ref(0)

function open(ev: MouseEvent) {
  ev.preventDefault()
  x.value = ev.clientX
  y.value = ev.clientY
  visible.value = true
}

function close() {
  visible.value = false
}

function onPick(item: CtxMenuItem) {
  if (item.disabled) return
  emit('select', item.key)
  close()
}

function onDoc() {
  close()
}

onMounted(() => document.addEventListener('click', onDoc))
onUnmounted(() => document.removeEventListener('click', onDoc))

defineExpose({ open, close })
</script>

<style lang="scss" scoped>
.vm-ctx-menu {
  position: fixed;
  z-index: 80;
  min-width: 140px;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card);
  box-shadow: var(--shadow-soft, 0 8px 24px rgb(0 0 0 / 8%));
}

.vm-ctx-menu__item {
  display: block;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--foreground);
  font-size: 13px;
  text-align: left;
  cursor: pointer;

  &:hover:not(:disabled) {
    background: var(--brand-soft);
    color: var(--brand);
  }

  &:disabled {
    opacity: 0.4;
    cursor: not-allowed;
  }
}
</style>
