<template>
  <div class="accordion">
    <div class="item" v-for="(item, index) in _arr">
      <div
        class="head flex items-center justify-between"
        @click="toggleOpen(item, $event)"
      >
        <div class="title-box">
          <span class="title">{{ item.title }}</span>
        </div>
        <DownOutlined class="collapse-icon" :class="{ rotate: item.open }" />
      </div>
      <div class="body" :style="{ height: item.height }">
        <slot :name="item.name" />
      </div>
    </div>
  </div>
</template>
<script name="Accordion" lang="ts" setup>
import { ref, watch, nextTick } from "vue";
import { DownOutlined } from "@ant-design/icons-vue";
interface AccordionItem {
  title: string;
  name: string;
  open?: boolean;
}
const props = withDefaults(
  defineProps<{
    arr: AccordionItem[];
  }>(),
  {
    arr: () => [],
  }
);
const _arr = ref<any>([]);
_arr.value = props.arr.map((item: AccordionItem) => {
  return {
    ...item,
    height: item.open ? "auto" : "0px",
    open: item.open || true,
  };
});

const toggleOpen = async (
  item: AccordionItem & { height?: any; open?: boolean },
  e: any
) => {
  const body = e.target.nextSibling;
  if (item.open && item.height === "auto") {
    let h = getComputedStyle(body).height;
    item.height = h;
    await new Promise((rs: any) => {
      setTimeout(() => {
        rs();
      }, 0);
    });
  }
  item.open = !item.open;
  if (item.open) {
    item.height = "auto";
    await nextTick();
    let comHeight = getComputedStyle(body).height;
    item.height = "0px";
    setTimeout(() => {
      item.height = comHeight;
    }, 0);
  } else {
    item.height = "0px";
  }
};

watch(
  () => props.arr,
  () => {
    _arr.value = props.arr.map((item: AccordionItem) => {
      return {
        ...item,
        height: item.open ? "auto" : "0px",
        open: item.open || true,
      };
    });
  }
);
</script>
<style lang="less" scoped>
.accordion {
  .item {
    .head {
      height: 32px;
      border-top: 1px solid #e5e5e5;
      border-bottom: 1px solid #e5e5e5;
      background: linear-gradient(180deg, #ffffff 0%, #f2f3f5 100%);
      padding: 0 16px;
      cursor: pointer;
      .title-box {
        .title {
          color: @text-color1;
          font-size: 14px;
          font-weight: bold;
        }
      }
      .collapse-icon {
        color: #8c8c8c;
        font-size: 12px;
        transition: all 0.2s;
        &.rotate {
          rotate: 180deg;
        }
      }
    }
    .body {
      transition: all 0.2s;
      overflow: hidden;
    }
  }
}
</style>
