<template>
  <Teleport to="body">
    <div v-if="open" class="smart-drawer-mask" @click.self="handleClose">
      <aside
        class="smart-drawer-shell"
        :class="drawerClass"
        role="dialog"
        aria-modal="true"
        :aria-labelledby="labelledById"
        :aria-label="dialogLabel"
        :aria-describedby="description ? descriptionId : undefined"
      >
        <header class="smart-drawer-header">
          <slot name="header">
            <div class="smart-drawer-heading">
              <p v-if="eyebrow" class="smart-drawer-eyebrow">{{ eyebrow }}</p>
              <h2 v-if="title" :id="titleId" class="smart-drawer-title">{{ title }}</h2>
              <p v-if="description" :id="descriptionId" class="smart-drawer-description">{{ description }}</p>
            </div>
          </slot>

          <div class="smart-drawer-actions">
            <slot name="head-actions" />
            <button class="smart-drawer-close" type="button" aria-label="关闭" title="关闭" @click="handleClose">
              <AppIcon name="close" />
            </button>
          </div>
        </header>

        <section class="smart-drawer-body">
          <slot v-if="$slots.default" />
          <slot v-else name="body" />
        </section>

        <footer v-if="$slots.footer" class="smart-drawer-footer">
          <slot name="footer" />
        </footer>
      </aside>
    </div>
  </Teleport>
</template>

<script setup>
import { computed, toRef, useId, useSlots } from "vue";

import { useBodyScrollLock } from "../composables/useBodyScrollLock";
import AppIcon from "./AppIcon.vue";

const props = defineProps({
  open: {
    type: Boolean,
    default: false
  },
  eyebrow: {
    type: String,
    default: ""
  },
  title: {
    type: String,
    default: ""
  },
  description: {
    type: String,
    default: ""
  },
  size: {
    type: String,
    default: "lg",
    validator: (value) => ["lg", "xl", "fullscreen"].includes(value)
  }
});

const emit = defineEmits(["close"]);
const slots = useSlots();
const titleId = `smart-drawer-title-${useId()}`;
const descriptionId = `smart-drawer-description-${useId()}`;

const drawerClass = computed(() => ({
  [`smart-drawer-${props.size}`]: true
}));

const labelledById = computed(() => (props.title && !slots.header ? titleId : undefined));
const dialogLabel = computed(() => (labelledById.value ? undefined : props.title || props.eyebrow || "业务抽屉"));

function handleClose() {
  emit("close");
}

useBodyScrollLock(toRef(props, "open"));
</script>
